对原型链的理解,__proto__和prototype究竟指向的是谁

大家好,第一次写技术文章,如有哪里写的不好还希望指出,也是为啦巩固下自己的知识

javascript里面的原型链属实让人头疼,经过一番查阅资料后,谈谈自己的原型链的认知

(不知道为什么proto两遍的两个下滑杠不显示啦,暂时先用,proto表示,回头知道啦,立刻回来更改)
首先我们大家要知道
1:proto 是隐式原型,prototype 是显示原型
2:所有的引用类型(数组,对象,函数),都有一个proto(隐式原型)属性,属性值是一个普通的对象;
3:所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通对象

首先谈一下 proto究竟指向的是谁


首先我们来创建一个空对象
var obj = {}  
obj.__proto__ === Object.prototype    //true
obj是由Object函数构建出的对象,由此可以证明 obj.__proto__ 指向的是构造它的函数

我们也可以显式原型Object函数来创建对象
var obj = Object.prototype
obj.__proto__ === Object.prototype    //true
由此可证明,obj的隐式原型就全等于Object的显示原型

当前我们得出结论 :当前对象是由谁构造的,那么proto就指向谁

那么prototype是谁呢?

现在我们知道,对象的proto属性是从构造它的函数的prototype那里得来的,那我们不禁要问,函数的prototype又是谁?

function fn1(){}
typeof fn1.prototype
//Object
console.log(fn1.prototype.constructor === fn1)
//true
console.log(fn1.prototype.__proto__ === Object.prototype)
//true

一般函数默认的prototype是一个类型为"object"的对象,它有两个属性:constructor和 proto。其中constructor属性指向这个函数自身,proto属性指向Object.prototype,这说明一般函数的prototype属性是由Object函数生成的。
当然也有特殊情况
有两个特殊的函数 那就是 Object函数和Function函数
先来看Object.prototype:

>typeof Object.prototype
"object"
>Object.prototype
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
    constructor: ƒ Object()
    hasOwnProperty: ƒ hasOwnProperty()
    isPrototypeOf: ƒ isPrototypeOf()
    propertyIsEnumerable: ƒ propertyIsEnumerable()
    toLocaleString: ƒ toLocaleString()
    toString: ƒ toString()
    valueOf: ƒ valueOf()
    __defineGetter__: ƒ __defineGetter__()
    __defineSetter__: ƒ __defineSetter__()
    __lookupGetter__: ƒ __lookupGetter__()
    __lookupSetter__: ƒ __lookupSetter__()
    get __proto__: ƒ __proto__()
    set __proto__: ƒ __proto__()

可以看到Object函数的prototype属性也是一个类型为"object"的对象,但和一般函数的默认prototype属性不一样的是,它多了一大堆方法,这些方法都是JavaScript对象的系统默认方法。
Object函数的prototype属性里没有proto属性,我们打印一下proto

console.log(Object.prototype.__proto__)
//null

大家可以看到打印出来的时候null,根据资料显示说是应为避免死循环
好让我们在打印一下Function函数

console.log(Function.prototype.__proto__)


{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
    constructor: ƒ Object()
    hasOwnProperty: ƒ hasOwnProperty()
    isPrototypeOf: ƒ isPrototypeOf()
    propertyIsEnumerable: ƒ propertyIsEnumerable()
    toLocaleString: ƒ toLocaleString()
    toString: ƒ toString()
    valueOf: ƒ valueOf()
    __defineGetter__: ƒ __defineGetter__()
    __defineSetter__: ƒ __defineSetter__()
    __lookupGetter__: ƒ __lookupGetter__()
    __lookupSetter__: ƒ __lookupSetter__()
    get __proto__: ƒ __proto__()
    set __proto__: ƒ __proto__()


您看是不是在哪见过,没错是 Object.prototype
为什么会是这样呢?
一个"function"类型的对象,应该是由Function函数生成的,那它的prototype属性应该指向Function.prototype,也就是Function.prototype.proto === Function.prototype。它和Object函数同样的问题出现了:循环引用。所以JavaScript规定Function.prototype.proto === Object.prototype,这样既避免了出现循环引用,又让proto构成的原型链指向了唯一的终点:Object.prototype.proto === null。

好啦以上就是我对原型链的理解,上面如果有哪里写的不对还望指出。

你可能感兴趣的:(对原型链的理解,__proto__和prototype究竟指向的是谁)