了解JS的原型链和继承

栏目: JavaScript · 发布时间: 4年前

内容简介:当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。1.调用toString方法时,会先在n实例上查找这个属性,没有找到?2.查找n的原型对象,就是Number.prototype(

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

了解JS的原型链和继承

eg1:

var n = new Number(1)
n.toString() // "1"
复制代码

1.调用toString方法时,会先在n实例上查找这个属性,没有找到?

2.查找n的原型对象,就是Number.prototype( n.__proto__ ), 我们可以看到

了解JS的原型链和继承

eg2:

var n = new Number(1)
n.hasOwnProperty('') // ""
复制代码

1.在n实例上没有找到hasOwnProperty方法

2.在n的原型对象上没有找到

3.在n的原型对象的原型对象上继续查找,找到了Object.prototype( n.__proto__.__proto__ )

了解JS的原型链和继承

原型对象和实例的关系

了解JS的原型链和继承
n.__proto__ === Number.prototype
复制代码

n即是Nubmer的实例,也是Object的实例

// 判断一个对象是构造函数的实例我们用instanceof
n instanceof Number // true
n instanceof Object // true
复制代码

因为所有的对象都是基于Object创建,所有的对象都是Object的实例

理解原型链是非常重要的,特别是在编写复杂的代码时

生成原型链的方式

使用语法结构创建对象:

var obj = {name: 'obj'}
// obj继承了Object.prototype的属性
// 原型链: obj ---> Object.prototype ---> null
复制代码
var arr = [1, 2, 3]
// arr继承了Array.prototype的属性(forEach)
// 原型链:arr ---> Array.prototype ---> Object.prototype ---> null
复制代码
function fun () {return 1}
// fun继承了Function.prototype的属性(call.apply)
// 原型链:fun ---> Function.prototype ---> Object.prototype ---> null
复制代码

使用构造函数创建对象

function Person () {
    this.type = []
}
Person.prototype.add = function (v) {
    this.type.push(v)
}
var p = new Person()
// p 拥有了构造函数Person的属性type, 且p.__proto__ = Person.prototype
复制代码

new关键字在这里做了什么?

var p = {};
Person.call(p)  //执行Person() this变量指向对象p, p拥有了Person的属性
p.__proto__ = Person.prototype // p继承了Person的原型对象

复制代码

构造函数与普通函数的区别

1.this指向不一样

2.构造函数默认返回实例对象

p.__proto__ === Person.prototype
// 返回简单数据类型
function Person () {
	var a = 1
	return a
}
var p = new Person() // Person
var p = Person() // 1
// 返回引用数据类型
function Person () {
	var a = {name: 'a'}
	return a
}
var p = new Person() // {name: 'a'}
var p = Person() // {name: 'a'}
复制代码

使用Object.create创建对象

var obj = {name: 'obj'} // obj是个实例对象
// 原型链:obj ---> Object.prototype ---> null

var child = Object.create(obj)
// 原型链:child ---> obj ---> Object.prototype ---> null
复制代码

object.create的实现方式:

Object.create =  function (o) {
    var F = function () {};
    F.prototype = o;
    return new F();
};
复制代码

继承方式

原型继承

方式1:

function Person () {
    this.type = ['good', 'bad']
}
Person.prototype.move = function () {
    console.log('gogogo')
}
function Child () {}
Child.prototype = new Person()
var child = new Child()
child.move() // gogogo
复制代码

方式2:

var child = Object.create(Person)
复制代码
了解JS的原型链和继承

问题在于原型链中的引用类型,被所有子类实例共享了,我们想要这样嘛? 为什么会这样呢?

var child1 = new Child()
var child2 = new Child()
child1.type.push('innocent')
child2.type // 'good', 'bad', 'innocent'
复制代码

我们先看下原型链: child1 ---> Child.prototype ---> Person.prototype

引用类型type对象是Child.prototype上面的属性, 所以子类的实例的type属性都是指向同一个Child.prototype.type

问题:父类实例的引用对象不共享,子类实例会共享? 因为new关键字

组合继承(构造加原型)

function Person () {
    this.type = ['good', 'bad']
}
Person.prototype.move = function () {
    console.log('gogogo')
}
function Child () {
    Person.call(this)
}
Child.prototype = new Person()
var child = new Child()
child.move() // gogogo
var child2 = new Child()
child.type.push('innocent')
child2.type // "good", "bad"
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

奔跑吧,程序员

奔跑吧,程序员

[美]叶夫根尼·布里克曼(Yevgeniy Brikman) / 吴晓嘉 / 人民邮电出版社 / 2018-7 / 99.00元

本书以软件工程师出身的创业者的角度,全面介绍了创业公司该如何打造产品、实现技术和建立团队,既是为创业者打造的一份实用入门指南,又适合所有程序员系统认识IT行业。书中内容分为三部分——技术、产品和团队,详细描绘创业的原始景象,具体内容包括:创业点子、产品设计、数据与营销、技术栈的选择、整洁的代码、软件交付、创业文化、招兵买马,等等。一起来看看 《奔跑吧,程序员》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具