理解原型链、prototype和__proto__

首先,明确两点

  1. JS所有对象(包括函数)都是Object的实例,并继承Object.prototype的属性和方法;
// 普通对象
const obj = {};
console.log(obj instanceof Object); // true
// 箭头函数
const myFun = () => {};
console.log(myFun instanceof Object); // true
// 函数表达式
const myFun2 = function() {};
console.log(myFun2 instanceof Object); // true
  • Object对象主要的属性和方法举例:
  • constructor属性:保存当前对象的构造函数
  • hasOwnProperty(propertyName)方法:判断该属性是否在当前对象实例中,而不是在对象的原型链中
  • isPrototypeOf(Object)方法:判断当前对象是否在传入的参数对象的原型链上Object.prototype.isPrototypeOf(obj)
  • propertyIsEnumerable(prototypeName)方法:判断给定的属性是否可以被for..in语句给枚举出来(比如constructor属性就不行)
  • toLocaleString()方法
  • toString()方法
  • valueOf()方法
  1. 对象在创建时,会有一些预定义的属性。定义普通对象时,会生成一个__proto__,它指向这个对象的构造函数的prototype。在定义函数时,会生成一个prototype,它同样是一个普通对象,里面包含指向构造函数的constructor以及一个__proto__,这个__proto__同样会指向这个函数的构造函数的prototype(一般为顶层Object,Object.prototype同样有一个__proto__,其值为null

JS数据类型有:
基本数据类型:String,Number,Boolean,Null,Undefined,Symbol
引用数据类型:Object,Array,Function
Array.prototype是一个数组,arr.__proto__同样是一个数组(其中,arr是Array的实例)

例如:

const fn = function(x) {
  this.x = x;
};
console.log(fn.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.isPrototypeOf(fn)); // true
console.log(fn instanceof Object); // true
// 实例化一个对象
const obj = new fn("123");
console.log(obj.__proto__ === fn.prototype) // true

解释下原型链:我们其实可以通过obj.toString()调用该方法,原理其实是,先会在obj这个对象上找有没有toString()方法,没有的话去obj.__proto__也就是fn.prototype上找,而在这个例子里也没有,那就沿着fn.prototype.__proto__向上找,就相当于Object.prototype,如果也没找到那就没有。

回过头来解释一下,为什么JS所有对象都是Object实例?

// 定义一个函数并实例化一个对象
const fun = function() {
  console.log("执行fun函数");
};
const obj = new fun();

console.log(obj instanceof fun) //true
console.log(obj instanceof Object) //true
console.log(fun instanceof Object) //true
  1. 第一个结果分析:obj 是对象,创建时会生成一个__proto__,它指向的是这个对象的构造函数的prototype,即fun函数的prototype(fun是一个函数,定义函数时会生成一个预定义属性prototype) ,执行obj instanceof fun 相当于判断obj.__proto__ === fun.prototype是否正确;
  2. 同样,fun函数的prototype也是一个对象,fun.prototype里面包含构造方法constructor以及__proto__;类似的,由于所有对象都是Object的实例,所以fun.prototype.__proto__指向的是构造函数,即最顶层Object的prototype。而instanceof在多层继承关系中同样有效,也就是说__proto__会一直向下传递,一直找到原型链的尽头。
  3. 而原型链的尽头是Object.prototype.__proto__ === null
console.log(fun.prototype.__proto__ === Object.prototype) //true

instanceof 用于判断一个变量是否某个对象的实例;
object instanceof constructor => 检测constructor.prototype是否在object的原型链上;在多层继承关系中,instanceof也同样适用

最后,我写的其实比较烂,当是学习笔记。推荐阅读我的一个大佬朋友的文章彻底弄懂原型与原型链

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值