当试图访问一个对象的属性时,它不单单在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。bash
var n = new Number(1)
n.toString() // "1"
复制代码
1.调用toString方法时,会先在n实例上查找这个属性,没有找到?app
2.查找n的原型对象,就是Number.prototype(n.__proto__
), 咱们能够看到函数
var n = new Number(1)
n.hasOwnProperty('') // ""
复制代码
1.在n实例上没有找到hasOwnProperty方法ui
2.在n的原型对象上没有找到this
3.在n的原型对象的原型对象上继续查找,找到了Object.prototype(n.__proto__.__proto__
)spa
n.__proto__ === Number.prototype
复制代码
n便是Nubmer的实例,也是Object的实例prototype
// 判断一个对象是构造函数的实例咱们用instanceof
n instanceof Number // true
n instanceof Object // true
复制代码
由于全部的对象都是基于Object建立,全部的对象都是Object的实例code
理解原型链是很是重要的,特别是在编写复杂的代码时cdn
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
复制代码
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'}
复制代码
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)
复制代码
问题在于原型链中的引用类型,被全部子类实例共享了,咱们想要这样嘛? 为何会这样呢?
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"
复制代码