- 每个实例对象( object )都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( __proto__ ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节
function doSomething(){}
doSomething.prototype.foo = "bar"; // add a property onto the prototype
var doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value"; // add a property onto the object
console.log( doSomeInstancing );
你会发现doSomeInstancing 中的__proto__是 doSomething.prototype,但这是做什么的呢?当你访问doSomeInstancing 中的一个属性,浏览器首先会查看doSomeInstancing 中是否存在这个属性。
如果 doSomeInstancing 不包含属性信息, 那么浏览器会在 doSomeInstancing 的 proto 中进行查找(同 doSomething.prototype). 如属性在 doSomeInstancing 的 __proto__ 中查找到,则使用 doSomeInstancing 中 __proto__ 的属性。
否则,如果 doSomeInstancing 中 __proto__ 不具有该属性,则检查doSomeInstancing 的 __proto__ 的 __proto__ 是否具有该属性。默认情况下,任何函数的原型属性 __proto__ 都是 window.Object.prototype. 因此, 通过doSomeInstancing 的__proto__ 的 __proto__ ( 同 doSomething.prototype 的 __proto__ (同 Object.prototype)) 来查找要搜索的属性。
如果属性不存在 doSomeInstancing 的 __proto__ 的 __proto__ 中, 那么就会在doSomeInstancing 的 __proto__ 的 __proto__ 的 __proto__ 中查找。然而, 这里存在个问题:doSomeInstancing 的 __proto__ 的 __proto__ 的 __proto__ 其实不存在。因此,只有这样,在 __proto__ 的整个原型链被查看之后,这里没有更多的 __proto__ , 浏览器断言该属性不存在,并给出属性值为 undefined 的结论。
- 不同对象继承的是什么
var o = {a: 1};
// o 这个对象继承了 Object.prototype 上面的所有属性
// o 自身没有名为 hasOwnProperty 的属性
// hasOwnProperty 是 Object.prototype 的属性
// 因此 o 继承了 Object.prototype 的 hasOwnProperty
// Object.prototype 的原型为 null
// 原型链如下:
// o ---> Object.prototype ---> null
var a = ["yo", "whadup", "?"];
// 数组都继承于 Array.prototype
// (Array.prototype 中包含 indexOf, forEach 等方法)
// 原型链如下:
// a ---> Array.prototype ---> Object.prototype ---> null
function f(){
return 2;
}
// 函数都继承于 Function.prototype
// (Function.prototype 中包含 call, bind等方法)
// 原型链如下:
// f ---> Function.prototype ---> Object.prototype ---> null
- 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链
function f(){}
f.prototype.b = 3
f.prototype.c = 3
// f.prototype = {b:3,c:4};
- 要检查对象是否具有自己定义的属性,而不是其原型链上的某个属性,则必须使用所有对象从
Object.prototype
继承的Object/hasOwnProperty
方法
hasOwnProperty是 JavaScript 中唯一一个处理属性并且不会遍历原型链的方法
tips: Object.keys()遍历时也不会遍历原型链
- prototype和实例的对象共享数据
function A 有一个叫做 prototype 的特殊属性。该特殊属性可与 JavaScript 的 new 操作符一起使用。对原型对象的引用被复制到新实例的内部 [[Prototype]] 属性。例如,当执行 var a1 = new A(); 时,JavaScript(在内存中创建对象之后,和在运行函数 A() 把 this 指向对象之前)设置 a1.[[Prototype]] = A.prototype;。然后当您访问实例的属性时,JavaScript 首先会检查它们是否直接存在于该对象上,如果不存在,则会 [[Prototype]] 中查找。 这意味着你在 prototype 中定义的所有内容都可以由所有实例有效地共享,你甚至可以稍后更改部分 prototype,并在所有现有实例中显示更改(如果有必要的话)
因此,当你执行:
var o = new Foo();
JavaScript 实际上执行的是:
var o = new Object();
o.__proto__ = Foo.prototype;
Foo.call(o);
网友评论