【JavaScript】JavaScript原型链之原型对象、实例和构造函数三者之间的关系

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32629809/article/details/78551274
  • 前言:用了这么久js,对于它的原型链一直有种模糊的不确切感,很不爽,隧解析之。
    本文主要解决的问题有以下三个:
    (1)constructor和prototype以及实例之间啥关系?
    (2)prototype是啥,proto又是啥,他们之间啥关系?
    (3)如果改变一个constructor的prototype,他的实例会发生什么变化?
    ok,下面一个一个解决。

(1)constructor和prototype以及实例对象三者之间啥关系?
举例:

function OMakeNewCar() {
}
console.info(OMakeNewCar.prototype.constructor === OMakeNewCar);        //输出 -> true

       如上,当我们创建一个函数,系统就会为这个函数自动分配一个prototype指针,指向它的原型对象。并且可以发现,这个原型对象包含两个部分(constructor__proto__),其中constructor指向函数自身。(这里形成一个小闭环
       当我们将该函数作为模板创建实例(new方法)的时候,我们发现创建出的实例是一个与构造函数同名的object,这个object是独立的,他只包含一个__proto__指针(实例没有prototype,强行访问则会输出undefined),这个指针指向上面提到的构造函数的prototype原型对象。
       这时候我们发现三者形成了一个大“闭环”。之所以加上引号,因为构造函数和实例之间无法直接访问,需要通过__proto__指针间接读取。

function OMakeNewCar() {
}
var car = new OMakeNewCar();
console.info(car.__proto__ === OMakeNewCar.prototype);      //输出 -> true
console.info(car.__proto__.constructor === OMakeNewCar);        //输出 -> true
  • 构造函数和原型以及实例对象三者之间关系如此下图所示

构造函数和原型以及实例对象三者之间关系

(2)prototype是啥,proto又是啥,他们之间啥关系?
在上一个问题中,我们用到了实例对象的proto指针,实际上在JavaScript中大部分类型的值都拥有proto属性,例如:

console.info('str'.__proto__);
//输出 -> String {length: 0, constructor: ƒ, charAt: ƒ, charCodeAt: ƒ, concat: ƒ, …}
console.info(NaN.__proto__);
//输出 -> Number {constructor: ƒ, toExponential: ƒ, toFixed: ƒ, toPrecision: ƒ, toString: ƒ, …}
console.info(true.__proto__);
//输出 -> Boolean {[[PrimitiveValue]]: false, constructor: ƒ, toString: ƒ, valueOf: ƒ}
console.info(OMakeNewCar.__proto__);
//输出 -> ƒ () { [native code] }

不过也有不存在proto属性的类型,如下:

console.info(undefined.__proto__);      //Cannot read property '__proto__' of undefined
console.info(null.__proto__);               //Cannot read property '__proto__' of null

然而,只有function对象才有prototype属性,其他任何类型的值都没有。即使是使用new方法从function构造出的实例对象也没有prototype属性。

var test = {};
test.prototype = function test() {
}
console.info(test.prototype.prototype);

(3)如果改变一个constructor 的prototype,他的实例会发生什么改变?
我们来做一个尝试:

var shape = function() {
};
var p = {
    a: function() {
        return 'aaaa';
    }
};
shape.prototype = p;            //更改原型,shape创建的对象就可以直接使用p对象里的属性
var circle = new shape();
console.info(circle.a());       //新对象可以直接使用p对象里的属性
展开阅读全文

没有更多推荐了,返回首页