资讯专栏INFORMATION COLUMN

Javascript基础之-原型(prototype)

laznrbfe / 937人阅读

摘要:实际上要分三种情况来看如果在链上存在这个属性,并且没有标记为只读,那么就会在本对象上新建一个新的同名属性。那么因为是引用,所以通过改变其原型上的的值,里也会跟着改变。反之,则新建一个对象。而这个引用链是可以根据自己的需求去改。

首先呢,prototype是对象里的一个内置属性,并且呢,这个属性是对于其他对象的一个引用。所以呢,思考下面的例子:

var obj = {
  a: 2
}
var myObj = Object.create(obj);
console.log(myObj.a); // 2
console.log(myObj === obj);  // false
console.log(Object.getPrototypeOf(myObj) === obj);  // true
Object.getPrototypeOf(myObj).a = 4
console.log(obj.a);  // 4

这里可以看到,实际上Object.create()是新建了一个对象,并且这个对象的prototype是obj的一个引用,所以呢,如果咱们直接修改prototype里面的值,原对象也就跟着变了。

很简单吧,那么如果执行如下代码的话,会发生什么呢?

myObj.a = 10;

是不是认为,还跟上面那个一样的,obj.a也变成10了呢?实际上不是的,他的运行机制要比咱们想的稍微复杂一点点。

实际上要分三种情况来看:

如果在prototype链上存在这个属性,并且没有标记为只读,那么就会在本对象上新建一个新的同名属性。

如果在prototype链上存在这个属性,并且标记为只读,那么将无法修改已有属性或在本对象上新建一个同名属性,如果是严格模式的话,还会报错。

如果在prototype链上只是存在此setter,那么一定会调用此setter,并不会添加属性到对象上,更不会重新定义这个setter

很枯燥是吧,来看例子,对照着上面的情况,好好的理解一下:

var obj = {
  a: 2,
  set c(num) {
    console.log("exec it");
  }
}
var myObj = Object.create(obj);
myObj.a = 10;
console.log(obj.a);  // 2
console.log(myObj.a);  // 10
Object.defineProperty(obj, "b", {
  value: 3,
  writable: false
})
myObj.b = 10;
console.log(myObj.b); // 3
myObj.c = 20;  // "exec it"
console.log(myObj.c);    // undefined

假如上面的已经理解了,那么可以思考下下面的运行结果:

var obj = {
  a: 2
}
var myObj = Object.create(obj);
console.log(++myObj.a);  // 3
console.log(obj.a);  // 2

这个在咱们实际的编码中时有发生,看代码是想把a改成3,但是由于上面第一种情况的影响,实际上是新建了一个同名属性3,并且赋值给了myObj。

上面我们谈论的都是普通对象的prototype的一些特性,接下来,咱们就要讲关于new关键字相关的一些知识点了,思考下面的例子

function Foo() {}
var a = new Foo();
console.log(Object.getPrototypeOf(a) === Foo.prototype);  // true
var b = new Foo();
Object.getPrototypeOf(b).saySomething = function () {
  console.log("say something");
}
a.saySomething();  // "say something"

很明显,在new的过程中呢,生成了一个新对象,并且把Foo.prototype引用到了新对象的prototype。那么因为是引用,所以通过b改变其原型上的prototype的值,Foo.prototype里也会跟着改变。

那么new的过程,是不是一定引用的是函数的prototype呢?也不一定,比如说下面的例子。

function Foo() {
  return {
    a: 3
  }
}
var a = new Foo();
console.log(Object.getPrototypeOf(a) === Foo.prototype);  // false
console.log(Object.getPrototypeOf(a) === Object.prototype); // true
console.log(a.a); // 3

在这个例子中,由于new的时候,返回的是一个对象,所以最后实际上a最终引用的是Foo最后返回的那个小对象,所以其prototype就是Object.prototype,而不是Foo.prototype

甚至说,Foo.prototype也是可以被改变的,不过在这时候,new出来的对象,其prototype就是被改过的那个对象。

var protoObj = {
  b: 10
}
function Foo() {}
Foo.prototype = protoObj;
var a = new Foo();
console.log(Object.getPrototypeOf(a) === Foo.prototype);  // true
console.log(Object.getPrototypeOf(a) === protoObj); // true
console.log(a.b); // 10

你看,如果prototypeObj修改了默认的Foo.prototype,所以最后,实际上形成了这么一个引用链:a.prototype => foo.prototype => protoObj=>Object.prototype。

所以说结论吧,在new的时候,实际上执行会包含这么几步,

如果有return并且返回的是一个对象的话,则直接返回return后的那个对象。

反之,则新建一个对象。

并且吧函数的prototype引用到新建对象的prototype中。

所以说,原型,可以理解为我本来对象有一个prototype,引用着其他的对象,当我这个对象的prototype引用了另一个对象的prototype,一般情况会到Object.prototype为止,这样就组成了一个原型链,原型链也就是互相引用的引用链。而这个引用链是可以根据自己的需求去改。

好了,简短的一小节就完事了,如果有不明白的,或者有疏漏的地方,或者有什么地方想和我讨论的,可以留言给我哦

本文转载自http://www.lht.ren/article/8/

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100935.html

相关文章

  • JavaScript基础创建对象、原型原型对象、原型

    摘要:在最开始的时候,原型对象的设计主要是为了获取对象的构造函数。同理数组通过调用函数通过调用原型链中描述了原型链的概念,并将原型链作为实现继承的主要方法。 对象的创建 在JavaScript中创建一个对象有三种方式。可以通过对象直接量、关键字new和Object.create()函数来创建对象。 1. 对象直接量 创建对象最直接的方式就是在JavaScript代码中使用对象直接量。在ES5...

    wangbjun 评论0 收藏0
  • javascript高级程序设计》第六章 读书笔记 javascript对象的几种创建方式

    摘要:三种使用构造函数创建对象的方法和的作用都是在某个特殊对象的作用域中调用函数。这种方式还支持向构造函数传递参数。叫法上把函数叫做构造函数,其他无区别适用情境可以在特殊的情况下用来为对象创建构造函数。 一、工厂模式 工厂模式:使用字面量和object构造函数会有很多重复代码,在此基础上改进showImg(https://segmentfault.com/img/bVbmKxb?w=456&...

    xiaotianyi 评论0 收藏0
  • SegmentFault 技术周刊 Vol.32 - 七夕将至,你的“对象”还好吗?

    摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...

    李昌杰 评论0 收藏0
  • SegmentFault 技术周刊 Vol.32 - 七夕将至,你的“对象”还好吗?

    摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...

    Lyux 评论0 收藏0
  • SegmentFault 技术周刊 Vol.32 - 七夕将至,你的“对象”还好吗?

    摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...

    AaronYuan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<