JavaScript 特殊之-prototype __proto__ class

时间:2021-07-13 18:48:51

刚学习JavaScript的时候,被告知,JavaScript并不是一门面向对象的语言,而是一门基于对象的语言,也就是万物皆对象.

Prototype:

注:只有函数对象才存在这个属性

这是一个函数对象的属性,用于指向原型对象

他存在的目的好像是多个实例对象共享一个对象的数据,旨在与对象__proto__属性配合,实现继承的效果

__proto__:

对象都拥有这个属性,ES6中箭头函数貌似不存在这个属性

他存在的目的:他就像是一个指针来指向自己构造函数的prototype属性指向的对象,用于寻找自己的继承的属性

我们看一个例子:

假设我们有一个对象obj

我们在使用obj.a时,系统都在做什么

它首先会在obj对象中寻找a属性的属性值,如果找不到就按照obj.__proto__对象是否存在a属性,直到寻找到Object.prototype,因为Object.prototype.__proto__属性指向的对象是null

所以,我们可以得出一个结论:__proto__属性,是一个指针,来指向被” 继承”的对象的,并用于查找属性的.

 

这里会产生两个问题:

1.     函数对象的prototype属性和对象属性__proto__关系是什么

其实,对于一个函数对象来说,他的prototype属性和他的__proto__属性其实一点关系都没有,但是对于用这个函数产生的对象来说就有和这个函数的prototype属性有关系了,有一个关系就是对象的__proto__属性==函数对象的prototype属性.

例如:

function A(){}//A这个对象拥有prototype属性和__proto__属性
var a=new A();//a这个对象只拥有__proto__属性
a.__proto__==A.prototype//true


从这里就能看出来function对象中的prototype属性只是为了,初始化实例对象的__proto__属性的

一个特殊的函数对象:Function

因为Function对象的构造函数是Function,所以Function对象的__proto__和Function.prototype是一样的

Function.__proto__==Function.prototype//true

2.     为什么,对象的最终属性__proto__都会指向Object.prototype

根据刚才的描述,所有通过new运算符分配出的对象的__proto__属性都是与[function].prototype相等的,

然而一个function被创建时的prototype属性是一个Object对象

验证:

A.prototype.__proto__==Object.prototype//true


而:

a.__proto__==A.prototype//true

于是所有的对象的链头都是Object.prototype

按照上述理论Object.prototype的__proto__的属性应该是Object.prototype

但是,它却是一个特例,指向的是null,为的是,寻找属性时,不造成死循环

我们在这里有一个技巧:

当我们想知道一个对象的__proto__属性到底指的是哪个对象,只要看他是什么类型的对象然后将这个类型对象.prototype返回就是__proto__.(当然,这是天然的__proto__的计算方法,然而__proto__属性是可以被赋值的)

 

然而,我想问为什么[function].prototype==[obj].__proto__

1.    new运算符在做什么

a.   创建一个新的对象,这个对象的类型是object

b.   设置这个新的对象的内部、可访问性和[[prototype]]属性为构造函数(指prototype.construtor所指向的构造函数)中设置的;

c.   执行构造函数,当this关键字被提及的时候,使用新创建的对象的属性;

d.   返回新创建的对象(除非构造方法中返回的是‘无原型’)。

 

代码实现:

functioncreatePerson(P) {
    var o = new Object();
    var args =Array.prototype.slice.call(arguments, 1);
    o.__proto__ = P.prototype;
    P.prototype.constructor= P;
    P.apply(o, args);
    return o;
}


2.    instanceof在干什么

当我们使用instanceof关键字时,系统在做什么?

我们做个试验(chrome console):

>functionB(){}
<undefined
>functionC(){}//先创建两个函数对象
<undefined
>var c=newC();//创建一个C的实例
<undefined
>c instanceofC
<true
>c instanceofB//显而易见的结果
<false
>c.__proto__=B.prototype//我们把原来的继承链修改
<B {}
>c instanceofB//结果变成了c是B的实例
<true
>c instanceofC//而不是C的实例(目前的继承链càB.prototype)
<false
>B.prototype.__proto__=C.prototype
//(目前的继承链càB.prototypeàC.prototype)
<C {}
>c instanceofC
<true


所以,我们可以看到instanceof的过程就是按照[obj]的继承连在验证[obj].__proto__是否等于[function].prototype

于是我们拿出原来的例子因为Object.prototype.__proto__==null

所以Object.prototypeinstanceof Object 返回的是false

 

ES6:class

对于ES6的class继承

class B extends A{}

需求有两个:

1.    B的实例对象要拥有A的所有属性super

2.    B的实例对象继承链要A.prototype B.prototype.__proto__=A.prototype

3.    B要有A的静态方法àB.__proto__=A