javascript 原型链详解 prototype和__proto__

来源:互联网 发布:翟欣欣的来历 知乎 编辑:程序博客网 时间:2024/05/29 11:44

我对原型链的理解就像是家谱,父-爷-太爷-----祖宗一样的家谱;但还不完全等同家谱,当一个函数或对象产生(或者说我们创建了一个对象或函数),就在原型链上产生了一个对应的存储空间,这个空间存放了这个函数或这个对象的所有内容,,,一般情况下我们调这个对象的某个属性时,这个对象会自行去原型链查找我们需要的东西,当他自身的原型链上没有我们需要的东西她就会去他的父级寻找,以此类推,如果我们实例化一个对象时,那么这个对象的实例和原对象的关系要通过原型链保持连接,换句话理解就是,父亲和儿子的关系是通过家谱或者理解为一个特殊的媒介才能保持联系,并相互影响;

谈到原型链就是在讲继承,在继承中,Javascript 只有一种结构:对象。每个对象都有一个私有属性(称为[[Prototype]]),它持有一个连接到另一个称为其 prototype 对象的链接。该原型对象具有一个自己的原型,该原型还有上一级的链接,直到达到一个对象的 prototype 为 null。根据定义,null 没有 prototype,并作为这个原型链 中的最后一个环节。
JavaScript中几乎所有的对象都是位于原型链顶端的Object的实例。
下面看一个原型链中一张很经典的原型链图:



可以理解为prototype为函数才有的属性__proto__是每个对象的属性(但__proto__属于非标准属性,对应的标准属性为[Prototype]),prototype的原型可以理解为原始、根、父类型。
__proto__示例

__proto__示例1
function Foo(){this.name="ranning"};var
f1=new Foo();
f1.__proto__.say=function(){
console.log("Hello")};
f1.say();// Hello
//对比上图f1的__proto__的原型链添加方法,f1可以调用这个很好理解;
__proto__示例2
function Foo(){this.name="ranning"};var
f1=new Foo();
Foo.__proto__.say=function(){
console.log("Hello")};
f1.say();//f1.say is not a function

Foo的__proto__的原型指向Function prototype,Foo的__proto__的原型链Foo.prototype指向(继承)Objective的原型链(Object prototype),和Function prototype,无直接关系,所以f1无方法,于是我们做下面的示例3
__proto__示例3
function Foo(){
this.name="ranning"
};
var a=new Foo();
Foo.__proto__.__proto__.say=function(){
console.log("Hello")
};
a.say();//Hello
Foo的__proto__的原型指向(继续)Function prototype,(Foo.__proto__==Function prototype;Foo.__proto__.__proto__==Object.prototype),Foo的__proto__的原型链Foo.prototype指向(继承)Objective的原型链(Object prototype)所以。。。。
特别注意:以上示例示例只是帮助理解__proto__的含义以及图形的意义,正常不会使用这个属性。

prototype示例


prototype示例1
function Foo(){
this.name="ranning"
};
var a=new Foo();
Foo.prototype.say=function(){console.log("Hello")};
a.say();// Hello//
prototype示例2
function Foo(){
this.name="ranning"
};
var a=new Foo();
Object.prototype.say=function(){
console.log("Hello")
};
a.say();// Hello

丛上面的例子中可以看出prototype的实例对象是没有这个属性,在w3school中介绍:prototype 属性使您有能力向对象添加属性和方法。

func.__proto__不应该与函数的func.prototype属性相混淆,而是指定在作为构造函数使用给定函数创建的对象的所有实例时分配的[[Prototype]]。Object.prototype属性表示Object的原型对象。





原型链相关属性及方法

hasOwnProperty
在原型链上查找属性比较耗时,对性能有副作用,这在性能要求苛刻的情况下很重要。另外,试图访问不存在的属性时会遍历整个原型链。
遍历对象的属性时,原型链上的每个可枚举属性都会被枚举出来。
检测对象的属性是定义在自身上还是在原型链上,有必要使用 hasOwnProperty 方法,所有继承自 Object.proptotype 的对象都包含这个方法
hasOwnProperty 是 JavaScript 中唯一一个只涉及对象自身属性而不会遍历原型链的方法。
确定某个对象是否具有带指定名称的属性。
object.hasOwnProperty(proName)
object: 必需。对象的实例。
proName: 必需。一个属性名称的字符串值。

特别注意:
function Foo(){
this.name="ranning"
};
var a=new Foo();
Foo.prototype.say=function(){
console.log("Hello")
};
此时Foo.hasOwnProperty("say");//false;
Foo.prototype.hasOwnProperty("say");//true;



isPrototypeOf():

The isPrototypeOf() method checks if an object exists in another object's prototype chain.
isprototypeof()方法检查对象是否存在于另一个对象的原型链。
function Foo() {}
function Bar() {}
function Baz() {}
Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);
var baz = new Baz();
console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true
 
阅读全文
0 0