js中的对象大多数都会有一个__proto__属性,该属性指向一个对象,当使用this查找属性时,就会沿着__proto_链查找,知道找到为止,否则返回undefined。
下面首先来看一下最为基础的__proto__,也即Object的prototype(Object是一个函数对象,js中所有函数都会有一个prototype属性)。
var o1= { a: 1 }; var o2 = new Object(); o2.a = 2;
以上代码在全局对象上添加了o1和o2两个属性,这两个属性分别指向两个对象,可以看到这两个对象的内容完全相同,并且都拥有一个__proto__。
以o1为例来看__proto__对象:
其中hasOwnProperty、isPrototypeOf、toString、valueOf都是对象比较常见的方法。
__defineGetter__/__defineSetter__看名字就知道是用来定义getter/setter的,猜测这两个方法是使用Object.defineProperty实现的,比如为对象o定义属性a的getter方法:
1 var o = { 2 get a(){ 3 return 2; 4 } 5 } 6 //其实就相当于 7 var o = Object.create(null); 8 Object.defineProperty(o, "a", { 9 get: function(){ 10 return 2; 11 } 12 });
__lookupGetter__/__lookupSetter猜测是用来查找某个属性的getter/setter方法的(因为在访问属性时,首先需要判断其是否存在getter/setter,如果存在则调用)。
get __proto__/set __proto__看名字就知道其是用来访问__proto__属性的(大多数对象都会拥有一个__proto__属性,在存取该属性时,就会顺着__proto__链找到这两个方法并调用。使用Object.create(null)创建的对象没有__proto__,也就没有这两个方法,我们只能通过Object.setPrototypeOf为该对象增加__proto__,所以猜测这两个方法其实就是在调用Object.getPrototypeOf和Object.setPrototypeOf)。