es6 prototype 属性和__proto__属性
prototype 属性和__proto__属性
大多数浏览器的 ES5 实现之中,每一个对象都有__proto__
属性,指向对应的构造函数的prototype
属性。ES6 Class 作为构造函数的语法糖,同时有prototype
属性和__proto__
属性,因此同时存在两条继承链。
(1)子类的__proto__
属性,表示构造函数的继承,总是指向父类。
(2)子类prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的prototype
属性。
class A {
}
class B extends A {
}
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
上面代码中,子类B
的__proto__
属性指向父类A
,子类B
的prototype
属性的__proto__
属性指向父类A
的prototype
属性。
这样的结果是因为,类的继承是按照下面的模式实现的。
class A {
}
class B {
}
// B 的实例继承 A 的实例
Object.setPrototypeOf(B.prototype, A.prototype);
// B 的实例继承 A 的静态属性
Object.setPrototypeOf(B, A);
const b = new B();
《对象的扩展》一章给出过Object.setPrototypeOf
方法的实现。
Object.setPrototypeOf = function (obj, proto) {
obj.__proto__ = proto;
return obj;
}
因此,就得到了上面的结果。
Object.setPrototypeOf(B.prototype, A.prototype);
// 等同于
B.prototype.__proto__ = A.prototype;
Object.setPrototypeOf(B, A);
// 等同于
B.__proto__ = A;
这两条继承链,可以这样理解:作为一个对象,子类(B
)的原型(__proto__
属性)是父类(A
);作为一个构造函数,子类(B
)的原型对象(prototype
属性)是父类的原型对象(prototype
属性)的实例。
Object.create(A.prototype);
// 等同于
B.prototype.__proto__ = A.prototype;
extends 的继承目标
extends
关键字后面可以跟多种类型的值。
class B extends A {
}
上面代码的A
,只要是一个有prototype
属性的函数,就能被B
继承。由于函数都有prototype
属性(除了Function.prototype
函数),因此A
可以是任意函数。
下面,讨论三种特殊情况。
第一种特殊情况,子类继承Object
类。
class A extends Object {
}
A.__proto__ === Object // true
A.prototype.__proto__ === Object.prototype // true
这种情况下,A
其实就是构造函数Object
的复制,A
的实例就是Object
的实例。
第二种特殊情况,不存在任何继承。
class A {
}
A.__proto__ === Function.prototype // true
A.prototype.__proto__ === Object.prototype // true
这种情况下,A
作为一个基类(即不存在任何继承),就是一个普通函数,所以直接继承Function.prototype
。但是,A
调用后返回一个空对象(即Object
实例),所以A.prototype.__proto__
指向构造函数(Object
)的prototype
属性。
第三种特殊情况,子类继承null
。
class A extends null {
}
A.__proto__ === Function.prototype // true
A.prototype.__proto__ === undefined // true
这种情况与第二种情况非常像。A
也是一个普通函数,所以直接继承Function.prototype
。但是,A
调用后返回的对象不继承任何方法,所以它的__proto__
指向Function.prototype
,即实质上执行了下面的代码。
class C extends null {
constructor() { return Object.create(null); }
}
实例的 __proto__ 属性
子类实例的__proto__
属性的__proto__
属性,指向父类实例的__proto__
属性。也就是说,子类的原型的原型,是父类的原型。
var p1 = new Point(2, 3);
var p2 = new ColorPoint(2, 3, 'red');
p2.__proto__ === p1.__proto__ // false
p2.__proto__.__proto__ === p1.__proto__ // true
上面代码中,ColorPoint
继承了Point
,导致前者原型的原型是后者的原型。
因此,通过子类实例的__proto__.__proto__
属性,可以修改父类实例的行为。
p2.__proto__.__proto__.printName = function () {
console.log('Ha');
};
p1.printName() // "Ha"
上面代码在ColorPoint
的实例p2
上向Point
类添加方法,结果影响到了Point
的实例p1
。
es6 prototype 属性和__proto__属性相关推荐
- JS中函数的prototype属性和对象的__proto__属性
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...
- JS中关于构造函数、原型链、prototype、constructor、instanceof、__proto__属性
在Javascript不存在类(Class)的概念,javascript中不是基于类的,而是通过构造函数(constructor)和原型链(prototype chains)实现的.但是在ES6中引入 ...
- es6 __proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()
__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf() JavaScript 语言的对象继承是通过原型链实现的.ES6 提供了更多原型对 ...
- javascript中的prototype原型、_proto_属性、原型链
prototype原型 JavaScript是面向对象的语言,那么继承自然是其重要特征之一.与标准面向对象语言不同,JavaScript继承主要通过prototype原型实现.每一个函数都具有prot ...
- ES6之符号与符号属性
引 在 JS 已有的基本类型(字符串.数值.布尔类型. null 与 undefined )之外, ES6 引入了一种新的基本类型:符号(Symbol).符号起初被设计用于创建对象私有成员,而这也是 ...
- javascript 原型属性(prototype 属性)与 实例属性(自身属性)
讲到原型属性,prototype属性,实例属性,自身属性,首先我们要明白这四者之间的关系.我查了一些资料,原型属性又叫prototype属性,实例属性又叫自身属性.只是叫法不同.下面我要引用他人写的一 ...
- es6 Class 的 new.target 属性
Class 的 new.target 属性 new是从构造函数生成实例对象的命令.ES6 为new命令引入了一个new.target属性,该属性一般用在构造函数之中,返回new命令作用于的那个构造函数 ...
- JS中的可枚举属性与不可枚举属性的学习以及扩展
最近在学习对象遍历的方法时总是能看到的两个词,一个是"原型",一个是"枚举属性".一开始感觉自己大概明白"枚举属性"的意思,但是叫我解释却又 ...
- Reflect.ownKeys()与Object.keys()区别 以及 JS中的可枚举属性与不可枚举属性
代码test1: var obj = {} Object.defineProperty(obj, 'method1', {value: function () {alert("Non enu ...
最新文章
- plt.figure(figsize(x,y))设置后后续程序都跟着改变,如何处理?走破解它!
- 设计模式-简单工厂模式
- DL之CNN:卷积神经网络算法简介之原理简介——CNN网络的3D可视化(LeNet-5为例可视化)
- 计算机动画的主要应用领域,简述计算机的主要特点和主要应用领域
- linux之ps命令
- canvasnest 移动距离_GitHub - XiaoxinJiang/canvas-nest: 仿知乎登录页面canvas-nest
- [渝粤教育] 西南科技大学 电气CAD 在线考试复习资料
- linux命令行中的大括号,linux命令行学习(19):花括号扩展(brace expansion)
- mac 安装 brew 镜像
- windows快捷键大全
- ubuntu14.04不能上网
- LINUX(CENTOS7.X)SVN部署文档+pycharmSvn
- 10行Python代码实现抽奖助手自动参与抽奖
- 日本人的姓及一些姓氏的读法(转)
- X86:2:X86处理器架构
- 香港服务器托管服务怎么样?
- 随记1 MySQL之特殊字符(表情)的存储以及读取乱码问题
- 【内网安全】——windows信息收集
- 佟年计算机天才不会打游戏,亲爱的热爱的:Gun神带佟年开黑,网友:甜蜜游戏时间...
- MIT-BIH心电数据库的使用