原型
原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是一个对象。
JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
可以访问对象不具有的属性而原型有的属性
function Person(){}
Person.prototype.name = 'haha'
var person = new Person();
当一个对象的原型中的属性它本身也有时,访问这个属性时不会往原型上寻找
function Person(){
this.name = '555'
}
Person.prototype.name = 'hah'
var person = new Person();
虽说可以通过对象访问到原型有的属性,但是不能修改它
function Person(){
}
Person.prototype.name = 'hah'
var person = new Person();
它会视为你在添加属性。
同样的,也不能通过对象删除原型中的属性
代码和上面的一样。
js中删除没有的属性会返回true
但我们可以看出并没有删除原型中的属性。
__proto__属性
起到对象和原型连接作用。
__proto__属性是可以被修改的,并且访问对象不存在的属性时就是沿着__proto__
function Person(){
}
var obj = {
name : 'hhh'
}
var person = new Person();
person.__proto__ = obj
原型链
function Grand(){
this.name = 'yeye'
}
var grand = new Grand();
function Father(){
this.name = 'baba'
}
Father.prototype = grand
var father = new Father();
function Son(){
this.name = 'erzi'
}
Son.prototype = father
var son = new Son();
可以看出来原型链带来的继承关系
一切对象的原型链的顶端都是Object(最终原型)
从上面的图可以看出来
泛泛地来讲,对象修改原型的属性是不行的,但是通过访问到的原型的某个属性,该属性是个Object,可以修改该属性内的属性
function Grand(){
this.name = 'yeye'
this.fortune = {
car : 'bmw'
}
}
var grand = new Grand();
function Father(){
this.name = 'baba'
}
Father.prototype = grand
var father = new Father();
这样的修改实际上通过了该对象的this进行了修改(或者添加)。
自增运算符能修改原型的值吗?不行
自增相当于取过来再加一然后赋值,最终变成了添加属性。
function Grand(){
this.money = 10
}
var grand = new Grand();
function Father(){
this.name = 'baba'
}
Father.prototype = grand
var father = new Father();
最终为father对象添加了一个money属性,而不是修改原型。
this的指向
a.b.c.d
这个.
前面的是谁,后面的方法中的this就指向谁
Person.prototype = {
name : 'xxx',
sex : 'male'
sayName : function(){
console.log(this.name)
},
saySex : function(){
console.log(this.sex)
}
}
function Person(){
this.sex = 'female'
}
var person = new Person();
Object.create()
更为方便的在原型链上创建一个对象
var obj = {
name = 'xx',
age = 20
}
var obj1 = Object.create(obj)
obj1
的原型就是obj
绝大多数的对象都会继承自Object.prototype
为什么是绝大多数呢?
原因来自于上面讲的Object.create()
从报错可以看出参数中可以是null
那我们用null
尝试一下。
可以看出这里创建的test
对象是没有__proto__
属性的。
即便人为的为它添加__proto__
属性,也不会起作用。