JavaScript原型链以及Object,Function之间的关系 后附两题

  JavaScript里任何东西都是对象,任何一个对象内部(null除外)都有另一个对象叫__proto__,即原型,它可以包含任何东西让对象继承。当然__proto__本身也是一个对象,它自己也有自己的__proto__,这样一级一级向上,就构成了一个__proto__链,即原型链。当然原型链不会无限向上,它有个终点,可以称为原型链的顶端,或者root,它是一个特殊的对象,它的__proto__为null。


obj.__proto__.__proto__......__proto__ === null;

  但是对象并不是凭空产生的,它一般是某一个class,或者确切说是构造函数的实例。JavaScript和其它面向对象的语言不太一样,Es6之前,它没有所谓的class,而是用函数来模拟class。定义了一个函数,实际上就定义了一个class,函数本身就是class的constructor,例如:

// Person函数是Function对象的一个实例
function Person() {
}

// new Person()返回来的是一个对象,它是Object的一个实例,是没有继承Function的
var p = new Person();

  这里创建了一个对象p,是Person的一个实例。既然p是一个对象,它就有原型__proto__,那p__proto__是怎么设定的?这里就引出了prototype,它是函数才有的一个属性,也是一个对象,一个函数创建的实例的__proto__就指向这个函数的prototype。所以p__proto__被设定为Person.prototype,即:


p.__proto__ === Person.prototype
// 实例对象原型的值为其对应构造函数显式原型的值即prototype的值

当然Person.prototype也是个对象,它自然也有__proto__,默认指向Object.prototype,即:


Person.prototype.__proto__ === Object.prototype

  而Object.prototype已经没有原型了,它的__proto__null

  以上就构成了由对象p开始的原型链:


p.__proto__ === Person.prototype
p.__proto__.____proto__ === Object.prototype

在这里插入图片描述

  JavaScript因此而推断出:


p instanceof Person=== true;
p instanceof Object === true;

  注意,这就是JavaScript判断一个对象是否instanceof某个函数的依据,即对象p的原型链上有没有一个__proto__是这个函数的prototype,如果有,那么p就是这个函数的instance。由于一般所有的原型链最终都会指向顶端的Object.prototype,所以它们都是Objectinstance

实现instance

/*A 表示左表达式,B 表示右表达式
A instanceof B 
如果B的显式原型在A的原型链上,返回true*/
function instance_of(A, B) {
    let R = B.prototype; // 取 B 的显示原型
    A = A.__proto__;// 取 A 的隐式原型
    // A的  __proto__  是不是强等于 B.prototype,不等于再找  A.__proto__ .__proto__  直到 __proto__ 为 null
    while (true) {
        if (A === null) return false;
        if (R === A) return true;
        A = A.__proto__;
    }
}

Function和Object的关系

  一般任何对象都是Object的instance,因为原型链的顶端都指向Object.prototype。那么Object本身是什么?Object也是个函数,而任何函数都是Function的实例对象,比如Array,String,当然Object也包括在内,它也是Function的实例,即:

// 首先Object和Function都是构造函数,而所有的构造函数的都是Function的实例对象. 因此Object是Function的实例对象
Object.__proto__ === Function.prototype;
Function.__proto__ === Function.prototype


Object instanceof Function === true

   同时,Function是个对象,它的原型是Function.__proto__,指向Function.prototype,并且这个原型链向上继续指向Object.prototype,即:

// Function.prototype是Object的实例对象 实例对象的原型会指向其构造函数的prototype属性
Function.prototype.__proto__ === Object.prototype

Function.__proto__.__proto__ === Object.prototype;

Function instanceof Object === true

这样就有了一个JavaScript里经常说到的蛋鸡问题:

Object instanceof Function === true
Function instanceof Object === true

“先鸡先蛋?”

总结

  • 每个对象都具有一个名为__proto__的属性
  • 每个构造函数都具有一个名为prototype的方法 ,所以prototype同样带有__proto__属性
  • 首先Object和Function都是构造函数,而所有的构造函数的都是Function的实例对象. 因此Object是Function的实例对象
  • Function.prototype是Object的实例对象
  • 当我们访问一个属性值的时候, 它会沿着原型链向上查找, 直到找到或者到Object.prototype.__proto__(为null)截止.

讲在后面

Function.prototype.a = 'a';
Object.prototype.b = 'b';

// Person函数才是Function对象的一个实例
function Person() {
}

// new Person()返回来的是一个对象,它是Object的一个实例,是没有继承Function的
var p = new Person();

/* p.__proto__ === Person.prototype
Person.prototype.__proto__ === Object.prototype
p.__proto__.____proto__ === Object.prototype*/


console.log('p.a: ' + p.a); 
// 自身找,没有 ==> 到原型上找(p.__proto__(Person.prototype)) 没有 ==> 到Person.prototype.__proto__(Object.prototype) 没有 undefined

console.log('p.b: ' + p.b); 
// 自身找,没有 ==> 到原型上找(p.__proto__(Person.prototype)) 没有 ==> 到Person.prototype.__proto__(Object.prototype) 找到b


// Person函数才是Function对象的一个实例

console.log('Person.a: ' + Person.a); 
// 自身找,没有 ==> 到原型上找(Person.__proto__(Function.prototype)) 找到 a 

// js里面所有对象都是Object的实例 Person函数可以访问到Object原型里面的属性

console.log('Person.b: ' + Person.b); 
// 自身找,没有 ==> 到原型上找(Person.__proto__(Function.prototype)) 没有,==> 到 Function.prototype.__proto__ === Object.prototype,找到b
var foo = {},
    F = function () {
    };

Object.prototype.a = 'value a';
Function.prototype.b = 'value b';

console.log(foo.a);   
// 自身找,没有 ==> 到原型上找(foo.__proto__(Object.prototype)),找到value a

console.log(foo.b); 
// 自身找,没有 ==> 到原型上找(foo.__proto__(Object.prototype)),没有 ==> 到foo.__proto__.__proto__ (Object.prototype.__proto__): 没有 undefined

console.log(F.a);
 // 自身找,没有 ==> 到原型上找(F.__proto__(Function.prototype)), 没有 ==> 到F.__proto__.__proto__(Object.prototype): 找到value a
 
console.log(F.b); 
// 自身找,没有 ==> 到原型上找(F.__proto__(Function.prototype)),找到value b

部分来源:https://www.cnblogs.com/web-record/p/9661804.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值