37

JavaScript 原型链与继承

 5 years ago
source link: https://blog.csdn.net/Simoral/article/details/88654934?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

版权声明:本文为simorel原创文章,未经simorel允许不得转载。 https://blog.csdn.net/Simoral/article/details/88654934

原型链与继承

系列文章

这是 JavaScript 系列文章:

文章目录

  1. ES6虽然引入了 class 关键字,但也只是语法糖,JavaScript仍然是基于原型的。
  2. JavaScript对象都是 Object 的实例
    z6jiAz3.png!web
  3. JavaScript 对象有一个指向一个原型对象的链。想要访问一个对象的属性,会顺着链搜寻,访问它的原型,以及原型的原型,直到找到要找到的属性,或者到达链尾的null。
  4. Object.prototype 属性表示 Object 的原型对象。
  5. proto 是一个隐含的私有属性, prototype 更像是一个公共属性,可以将一些共同的属性设置在这个属性下。

原型链的继承

属性继承

/** 写法一 */
let parent = function () {
	this.a = 1;
	this.b = 2;
}

/** 写法二,此写法效果同写法一
function parent() {
	this.a = 1;
	this.b = 2;
}
*/

let child = new parent();  // { a: 1, b: 2 }

// 在parent原型上定义属性
parent.prototype.b = 3;
parent.prototype.c = 4;

// 不要直接使用 parent.prototype = { b: 3, c: 4 }; 这样会破坏原型链
// child.[[prototype]] / child.__proto__ / child.constructor.prototype 有属性b和c

// child.[[prototype]].[[prototype]] 和 child.prototype. 效果相同
// child.[[prototype]].[[prototype]].[[prototype]] 是 null
// null 没有 [[prototype]]
// 原型链: child({ a: 1, b: 2 }) --> parent({ b: 3, c: 4 }) --> Object.prototype --> null

// 'a'是child的自身属性
// 'b'是child的自身属性,虽然原型上也有一个'b'属性,但是不会被访问到,这个就叫做“属性遮蔽”
// 'c'不是child的自身属性,查找原型上是否有此属性,'c'是child.[[prototype]]的属性么?答案是肯定的。
// 'd'不是child的自身属性,查找原型上是否有此属性,仍然没有,再查找原型的原型,child.[[prototype]].[[prototype]]为null,所以停止搜索,返回undefined

方法继承

任何函数都能添加到对象上作为对象的属性。并且具备属性继承的各种特点,包含“属性遮蔽”。

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

let parent = {
	a: 2,
	m: function() {
		return this.a + 1;
	}
};

// 调用parent.m时,‘this’指向parent.
console.log(parent.m());  // 3

// child是一个继承自parent的对象
let child = Object.create(parent);

child.a = 4;  // 创建child的自身属性a
console.log(parent.m());  // 5
// 此时‘this’指向child对象,‘this.a’即p.a,

生成原型链

// o 继承了 Object.prototype 上面的所有属性
// o 没有 hasOwnProperty 属性,但是 Object.prototype 有 hasOwnProperty 属性
// 原型链:o --> Object.prototype --> null
let o = {a: 1};

// 数组都继承于 Array.prototype 
// 原型链:a ---> Array.prototype ---> Object.prototype ---> null
let a = ["yo", "whadup", "?"];

// 函数都继承于Function.prototype
// 原型链: f ---> Function.prototype ---> Object.prototype ---> null
function f () {}

构造方法

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

function Graph() {
  this.vertices = [];
  this.edges = [];
}

Graph.prototype = {
  addVertex: function(v){
    this.vertices.push(v);
  }
};

// g是生成的对象,他的自身属性有'vertices'和'edges'.
// 在g被实例化时,g.[[Prototype]]指向了Graph.prototype.
var g = new Graph();
"use strict";

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(sideLength) {
    super(sideLength, sideLength);
  }
  get area() {
    return this.height * this.width;
  }
  set sideLength(newLength) {
    this.height = newLength;
    this.width = newLength;
  }
}

var square = new Square(2);

Object.create()

新对象的原型就是调用 create 方法时传入的第一个参数

var a = {a: 1};   // a ---> Object.prototype ---> null

var b = Object.create(a);  // b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (继承而来)

var c = Object.create(b);  // c ---> b ---> a ---> Object.prototype ---> null

var d = Object.create(null);  // d ---> null
console.log(d.hasOwnProperty); // undefined, 因为d没有继承Object.prototype
  • hasOwnProperty 是 JavaScript 中处理属性并且不会遍历原型链的方法之一。(另一种方法: Object.keys())

  • 注意:检查属性是否undefined还不够。该属性可能存在,但其值恰好设置为undefined

错误示例

扩展内置原型的唯一理由是支持JavaScript 引擎的新特性

  1. 各种专属名词解释:

    原型

    原型对象

    实例

参考链接

[1] MDN, 继承与原型链

[2] 阮一峰, Javascript继承机制的设计思想

[3] 阮一峰, Javascript 面向对象编程(一):封装

[4] 阮一峰, Javascript面向对象编程(二):构造函数的继承

[5] 阮一峰, Javascript面向对象编程(三):非构造函数的继承

感谢


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK