<>原型链与继承

<>系列文章

这是JavaScript系列文章:

* 类 <https://blog.csdn.net/Simoral/article/details/88390199>
* promise <https://blog.csdn.net/Simoral/article/details/88527020>
* async & await <https://blog.csdn.net/Simoral/article/details/88633248>
* 原型链与继承 <https://blog.csdn.net/Simoral/article/details/88654934>
* 闭包 <https://blog.csdn.net/Simoral/article/details/88685869>
* this <https://blog.csdn.net/Simoral/article/details/88707877>
* CommonJS <https://blog.csdn.net/Simoral/article/details/88573465>
* ES6 Module <https://blog.csdn.net/Simoral/article/details/88721700>


文章目录

* 原型链与继承 <https://blog.csdn.net/Simoral/article/details/88654934#_0>
* 系列文章 <https://blog.csdn.net/Simoral/article/details/88654934#_6>
* 简述 <https://blog.csdn.net/Simoral/article/details/88654934#_23>
* 原型链的继承 <https://blog.csdn.net/Simoral/article/details/88654934#_31>
* 属性继承 <https://blog.csdn.net/Simoral/article/details/88654934#_32>
* 方法继承 <https://blog.csdn.net/Simoral/article/details/88654934#_67>
* 生成原型链 <https://blog.csdn.net/Simoral/article/details/88654934#_91>
* 语法 <https://blog.csdn.net/Simoral/article/details/88654934#_92>
* 构造方法 <https://blog.csdn.net/Simoral/article/details/88654934#_108>
* class <https://blog.csdn.net/Simoral/article/details/88654934#class_127>
* Object.create()
<https://blog.csdn.net/Simoral/article/details/88654934#Objectcreate_154>
* 性能 <https://blog.csdn.net/Simoral/article/details/88654934#_168>
* 错误示例 <https://blog.csdn.net/Simoral/article/details/88654934#_173>
* 问题 <https://blog.csdn.net/Simoral/article/details/88654934#_176>
* 参考链接 <https://blog.csdn.net/Simoral/article/details/88654934#_183>


<>简述

* ES6虽然引入了class关键字,但也只是语法糖,JavaScript仍然是基于原型的。
* JavaScript对象都是Object的实例

* JavaScript
对象有一个指向一个原型对象的链。想要访问一个对象的属性,会顺着链搜寻,访问它的原型,以及原型的原型,直到找到要找到的属性,或者到达链尾的null。
* Object.prototype 属性表示 Object 的原型对象。
* 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();
<>class
"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] MDN, 继承与原型链
<https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain>
[2] 阮一峰, Javascript继承机制的设计思想
<http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html>
[3] 阮一峰, Javascript 面向对象编程(一):封装
<http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html>
[4] 阮一峰, Javascript面向对象编程(二):构造函数的继承
<http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html>
[5] 阮一峰, Javascript面向对象编程(三):非构造函数的继承
<http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html>

感谢

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信