前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ES6:原型、类、继承

ES6:原型、类、继承

作者头像
WEBJ2EE
发布2019-07-19 11:55:21
7670
发布2019-07-19 11:55:21
举报
文章被收录于专栏:WebJ2EEWebJ2EE

下面是用 ES6 语法

写的类式继承

图1:ES6 的面向对象高仿语法

很完美、很 Java 有木有 ...

这 ... 也再次证明了 ...

JavaScript 确实很牛逼 ...

但是

虽然我们可以用

class、extends、new、instanceof

写出高仿 Java 的类与继承

但它的原理、特性

与 Java 完全是两码事

下面进入今天的正题

JavaScript 没有类只有对象!所谓的类、继承都只是借助 JavaScript 原型链机制模拟实现的。事实上 ES6 中新加入的 class、extends、super 关键字也只不过是现有原型链特性的语法糖,只是起到了简化编程的作用。

1. 函数、构造函数、new

JavaScript 函数:

  • 函数是第一类对象(first-class object);
  • 函数也是一个包含了方法(call、apply)和属性(length、prototype)的对象;
  • 所有函数都是由 Function() 构造函数创建的;

图2:用 Function 生产一个函数

图3:查看函数对象拥有的属性与方法

“构造函数”与 new:

图4:演示构造函数与 new

实际上,NothingSpecial 和你程序中的其他函数没有任何区别。函数本身并不是构造函数,然而,当你在普通的函数调用前面加上 new 关键字之后,就会把这个函数调用变成一个“构造函数调用”。实际上,new 会劫持所有普通函数并用构造对象的形式来调用它。

——《你不知道的 JavaScript (上卷)》p150

换句话说,在 JavaScript 中对于“构造函数”最准确的解释是,所有带 new 的函数调用

——《你不知道的 JavaScript (上卷)》p150

2. prototype、[[Prototype]]、__proto__

  • 每个函数都有一个名为 prototype 的属性,它指向原型对象。
  • 所有创建的对象实例共享该原型对象,且这些对象实例可以访问原型对象的属性。
  • 所有创建的对象实例通过内部属性 [[Prototype]] 与构造函数的 prototype 建立联系;
  • 现代浏览器中可通过属性 __proto__ 访问这个内部属性 [[Prototype]];

[[试试牛刀]]

如果都能给出答案

你已经掌握 JavaScript 的终极奥义

前端扛把子就是你

图5:原型小测试

[[原理分析]]

[[答案公布]]

3. .constructor 属性不可靠、不安全

.constructor 从哪来?

.constructor 为啥不靠谱?

Car.prototype 的 .constructor 属性只是 Car 函数在声明时的默认属性。如果你创建了一个新对象并替换了函数默认的 .prototype 对象引用,那么新对象并不会自动获得 .constructor 属性

.constructor 并不是一个不可变属性。它是不可枚举的,但是它的值是可写的。你可以任意对其赋值。所以 .constructor 是一个非常不可靠并且不安全的引用。

.constructor 该如何利用?

虽然 .constructor 属性不可靠也不安全,但是它可以很方便的用于运行时对象的内省。可以重置 .constructor 属性使其指向期望的构造函数而不会影响其功能,这是由于该属性主要是用于提供对象的信息。

——《JavaScript 模式》

图8:使用.constructor属性的正确姿势

4. instanceof 的本质是什么?

在传统面向类环境中(例如:Java),检查一个实例的继承祖先通常使用 instanceof 关键字实现;

Java 怎么用 instanceof 的?

Java 有的,JavaScript 也有

但是

不要被表象蒙蔽

john instanceof Employee john instanceof Person

JavaScript 中,instanceof 操作符的左操作数是一个普通的对象,右操作数是一个函数。instanceof 回答的问题是:在 john 的整条 [[Prototype]] 链中是否有 Employee.prototype 指向的对象?

Employee.prototype.isPrototypeOf(john) Person.prototype.isPrototypeOf(john)

ES6 的 .isPrototypeOf 接口还原了 instanceof 操作符的本质含义;

举例说明

5. 模拟类式继承的常见方法

5.1. 原型链继承

5.2. 借用构造函数

5.3. 组合继承*(原型链继承 + 借用构造函数)

5.4. 共享原型

5.5. 临时构造函数

上面几种模拟继承的方法各有利弊

篇幅有限,水平一般

建议大家

6. ES6 新特性

ES6 提供了更接近传统语言的语法,通过 class 关键字可以定义类。ES6 中的 class可以看作只是一个语法糖,新的 class 写法只是让对象原型的写法更加清晰,更像面向对象编程的语法而已

——《ES6 标准入门》

参考:

《JavaScript 启示录》 《JavaScript 忍者秘籍》 《JavaScript 模式》 《你不知道的 JavaScript (上卷)》 《JavaScript 面向对象精要》 《JavaScript 面向对象编程指南》 《深入理解 ES6》 《ES6 标准入门》 《JavaScript 框架设计》

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WebJ2EE 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档