原型链与继承

当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object )都有一个私有属性(称之为proto)指向它的原型对象(prototype)。该原型对象也有一个自己的原型对象(proto) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

新建函数,并创建对象

function Car() {this.name = 'BMW'this.price = 95800
}
let carBMW = new Car()

这时我们的脑海里应该有这样一张图:

或许你跟我初次接触一样。如果对该图不怎么理解,不要着急,继续往下看!!!

基于原型链的继承

JavaScript 对象是动态的属性“包”(指其自己的属性)。JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

从 ECMAScript 6 开始,[[Prototype]] 可以通过Object.getPrototypeOf()和Object.setPrototypeOf()访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 __proto__。

接着上述代码

console.log(carBMW)  // *Car {name: "BMW", price: 95800}*

在 Car() 函数的原型上定义属性

Car.prototype.price = 200000
Car.prototype.speed = 300console.log(carBMW.__proto__)  // {price: 200000, speed: 300, constructor: ƒ}
console.log(carBMW.__proto__.__proto__ == Object.prototype)  // true
console.log(carBMW.__proto__.__proto__.__proto__) // null

综合上述代码,可以给出如下原型链

{name: "BMW", price: 95800} ---> {price: 200000, speed: 300, constructor: ƒ} ---> Object.prototype ---> null

继续写代码

console.log(carBMW.name)   // BMW
// name 为 carBMW 自身的属性console.log(carBMW.price)  // 95800
// price 为 carBMW 自身的属性,原型上也有一个'price'属性,但是不会被访问到,这种情况称为"属性遮蔽 (property shadowing)"console.log(carBMW.speed)  // 300
// speed 不是 carBMW 自身的属性,但是 speed 位于该原型链上,因此我们依然可以取到该值// 当然如果你试着访问一个不存在原型链上的属性时,这时候会给你返回一个undefined

当我们给对象设置一个属性时,创建的属性称为对象的自有属性。

函数的继承与其他的属性继承没有差别,包括上面的“属性遮蔽”(这种情况相当于其他语言的方法重写)。

当继承的函数被调用时,this 指向的是当前继承的对象,而不是继承的函数所在的原型对象。

let car = {price: 95800,getPrice: function(){return this.a}
}console.log(car.getPrice()); // 95800
// 当调用 car.getPrice() 时,'this'指向了car.let bmw = Object.create(car);
// bmw 是一个继承自 car 的对象bmw.price = 400000; // 创建 bmw 的自身属性 price
console.log(bmw.getPrice()); // 400000
// 调用 bmw.getPrice() 时, 'this'指向 bmw.
// 又因为 bmw 继承 car 的 getPrice 函数
// 此时的'this.price' 即 bmw.a,即 price 的自身属性 'price' 

虽然有点绕,细读之后逻辑并不是很复杂

多种方法创建对象

基于字面量创建对象

也就是根据相应的语法结构直接进行创建

let car = {price: 95800,getPrice: function(){return this.a}
}
// car 为一个对象,因此相应的原型链应该如下
// car ---> Object.prototype ---> nulllet cars = ['BMW','Audi','WulingHongguang']
// cars 为一个数组对象,相应的原型链应该如下
// cars ---> Array.prototype ---> Object.prototype ---> null

基于构造函数创建对象

在 JavaScript 中,构造器其实就是一个普通的函数。当使用 new 操作符 来作用这个函数时,它就可以被称为构造方法(构造函数)。

function Car() {this.name = 'BMW'this.price = 95800
}
Car.prototype.speed = 300
let car = new Car()
// 可以知道,car 的自身属性 {name: "BMW", price: 95800}, 位于原型链上的属性有 speed .

基于Object.create()创建对象

ECMAScript 5 中引入了一个新方法:Object.create()。可以调用这个方法来创建一个新对象。新对象的原型就是调用 create 方法时传入的第一个参数

var car = {price: 10000};
// car ---> Object.prototype ---> nullvar carBMW = Object.create(car);
// carBMW ---> car ---> Object.prototype ---> null
console.log(carBMW.price); // 10000 (继承而来)

基于 Class 关键字创建对象

ECMAScript6 引入了一套新的关键字用来实现 class。实质上还是语法糖,底层原理依旧不变

class Point {constructor(x, y) {this.x = x;this.y = y;}toString() {return '(' + this.x + ', ' + this.y + ')';}
}
var point = new Point(2, 3);
point.toString() // (2, 3)
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true

以上代码中,x和y都是实例对象point自身的属性(因为定义在this变量上),所以hasOwnProperty方法返回true,而toString是原型对象的属性(因为定义在Point类上),所以hasOwnProperty方法返回false。这些都与ES5的行为保持一致。

深入理解 js 之继承与原型链相关推荐

  1. js的继承和原型链(更新中)

    话不多说,直接上MDN链接 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_ ...

  2. JavaScript面向对象——深入理解默认的继承方式原型链

    描述: 正如我们所了解,JavaScript中的每个函数中都有一个指向某一对象的prototype属性.该函数被new操作符调用时会创建并返回一个对象,并且该对象中会有一个指向其原型对象的秘密链接,通 ...

  3. 【JS继承】JS继承之原型链继承

    自我介绍:大家好,我是吉帅振的网络日志:微信公众号:吉帅振的网络日志:前端开发工程师,工作4年,去过上海.北京,经历创业公司,进过大厂,现在郑州敲代码. JS继承专栏 1[JS继承]什么是JS继承? ...

  4. ES5常用的组合继承及原型链理解

    ES5常用的组合继承及原型链理解 <!DOCTYPE html> <html lang="en"><head><meta charset= ...

  5. JS中对象的四种继承方式:class继承、原型链继承、构造函数继承、组合继承(构造函数和原型链继承的结合)

    前言 才发现之前没有对JavaScript中的继承做过总结,不过看得到是不少,接下来就对这几种继承方式做一下总结. class继承 class继承是ES6引入的标准的继承方式. ES6引入了class ...

  6. JavaScript之继承(原型链)

    JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...

  7. 一篇JavaScript技术栈带你了解继承和原型链

    作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...

  8. 学习es6的继承与原型链

    es6出现了class类但是此类非彼类和java不一样 上代码 这是typescript未编译的样子 class Pepole{age:number=nullname:string="&qu ...

  9. JavaScript原型彻底理解2---继承中的原型链

    一.继承的概念 继承是所有的面向对象的语言最重要的特征之一.大部分的oop语言的都支持两种继承:接口继承和实现继承.比如基于类的编程语言Java,对这两种继承都支持.从接口继承抽象方法 (只有方法签名 ...

最新文章

  1. tcp retransmission 出现的原因_为什么 TCP 会被 UDP 取代?
  2. ThreeJS 屏幕坐标与世界坐标互转
  3. SpringBoot+MyBatisPlus实现插入关联多表数据的接口(企业质检管理举例)
  4. 安卓dts音频解码_DTS音效、解码、编码概念剖析
  5. 【javascript】操作符:一元操作符
  6. rdlc报表 矩形高固定_固定资产条码管理系统特点分析
  7. orange pi java_[中文]Orange Pi家族各大成员一览表
  8. MVC.Net: jqueryval错误
  9. 一个SQL逻辑读异常的解决方法
  10. [转载] 分布式系统trace实践
  11. 《iOS9开发快速入门》——第1章,第1.4节小结
  12. keepalived+Nginx实现Web高可用
  13. 稀疏矩阵的创建--十字链表
  14. 2014-03-18
  15. 'Data_Label_Tools - 开源数据标注工具大列表
  16. 【NLP】第 6 章:XGBoost 超参数
  17. 【富文本】2.windows或office原版镜像怎么下载,msdn.itellyou上面列的项目的详细解读
  18. 2021年“上海区块链周”参会随感(二)2021-04-12
  19. perl和python各自擅长的领域
  20. 夜里走了很多路,醒来还是在床上

热门文章

  1. 简单module_深入理解JavaScript之全面解析Module模式
  2. wince 微软服务器,大众拥抱微软 推出WinCE 4.0 Pocket PC
  3. C++字符串完全指引之二 —— 字符串封装类
  4. 从零开始单排学设计模式「策略模式」黑铁 II
  5. 非变动性算法源代码分析与使用示例( for_each、min_element 、find_if、search 等)...
  6. Redis的二八定律
  7. IE打印控件推荐-4fang pazu
  8. socket 编程入门教程(一)TCP server端:3、sockaddr与sockaddr_in
  9. 诡异的bug: tcsh陷入死循环
  10. 史记.饭岛爱列传(转)