Js中prototype、[[prototype]]和__proto__的区别和⽤法
⼀.显式原型&隐式原型
显式原型:prototype
隐式原型:__proto__
1.1 Important
__proto__是每个对象都具有的属性
prototype是Function独有的属性
1.2 Tips
对象的隐式原型的值为其对应构造函数的显式原型的值
fn.__proto__ === Function.prototype
函数的prototype属性是定义时⾃动添加的。默认为{}
对象的__proto__属性是创建对象时⾃动添加的,默认值为其构造函数的prototype
Object.prototype.__proto__ === null
1.3 说了这么多和[[prototype]]有什么关系?
其实[[prototype]]和__proto__意义相同,均表⽰对象的内部属性,其值指向对象原型。前者在⼀些书籍、规范中表⽰⼀个对象的原型属性,后者则是在浏览器实现中指向对象原型。
⼆.作⽤
作⽤⽅⾯来讲当然是实现继承了。其中最经典的共享属性⽅法的原型链继承。其中必不可少的属性就是__protoo__和prototype。
我们举个栗⼦
function Son(){}
function Father(){}
Son.prototype =new Father();
如此即实现了继承
我们可以写代码进⾏验证
Foo.prototype.__proto__ === Bar.prototype  //true
符合上述第三条规则,所以可以通过此⽅法完成函数的继承。
注意,此为原型链继承,其中的⽅法鱼属性为此链上的所有实例所共享
三.教你⼿撸原型链
原型链⽆⾮就是⼀堆继承关系:
我们只需要将⼉⼦原型的__proto__属性指向⽗亲的prototype属性,构造函数的prototype属性的constructor属性指向其本⾝即可。
不过需要注意的⼀点是,已经被实例化的对象__proto__属性指向其构造函数的prototype。
另外⼀个特殊的对象Object。作为所有对象的⽗类他的原型的__proto__属性指向null
如此我们就可以看得懂那张经典的原型链图解啦
四.从原理讨论原型链的⽤处
4.1 typeof
typeof作为《JavaScript⾼级程序设计》中⾸推的判断类型⽅法⽆疑是⼤多数⼈的选择。不过令⼈烦恼的是我们发现当碰
到Array、Function等类型时他均返回⼀个Object。这就有点⽓⼈了。所以机智的玩家们采取了String.call(obj)⽅法来识别对象类型。他会返回⼀个"[object Type]"的东西来告诉你所指对象的类型。
此处就⽤到了原型链必不可少的prototype。通过改变this指针指向将我们所要验证类型的对象。以完成类型的检验
4.2 instanceof
除去typeof外我们还有另⼀个⽅法:instanceof
看过我之前转载的关于typeof与instanceof原理的好兄弟估计会猜到我要说什么,不过我还是要继续BB。
instanceof这个⽅法⽤于判断某实例是否从属于某种类型,同时也可以判断⼀个实例是否是其⽗类型或者祖先类型的实例。举个栗⼦
function Son(){}
function Father(){}
Son.prototype =new Father();
var son =new Son();
son instanceof Son  //true
son instanceof Father  //true
看见没,只要你是这⼀家⼦的⼈(实例)那你⽆论⾛哪这祖宗祠堂(原型链上的⽼东西们)都认你。那么他们是如何判断你是不是这家的⼉孙呢?当然是原型链。我们来试着写⼀串伪代码来进⾏验证
function new_instance_of(leftVaule, rightVaule){
let rightProto = rightVaule.prototype;// 取右表达式的 prototype 值    leftVaule = leftVaule.__proto__;//
取左表达式的__proto__值while(true){
if(leftVaule ===null){
typeof的用法return false;
}
if(leftVaule === rightProto){
return true;
}
leftVaule = leftVaule.__proto__
}
}
如此这般,通过原型链认祖归宗。咱们看看是否有⽤
new_instance_of(son, Son)// true
new_instance_of(son, Father)// true
今天的内容就这么多