原型对象
在JavaScript中,我们创建一个函数A(就是声明一个函数), 那么浏览器就会在内存中创建一个对象B,而且每个函数都默认会有一个属性 prototype 指向了这个对象( 即:prototype的属性的值是这个对象 )。这个对象B就是函数A的原型对象,简称函数的原型。这个原型对象B 默认会有一个属性 constructor 指向了这个函数A ( 意思就是说:constructor属性的值是函数A )。
代码:
function Person(){
}
function Animal(grander,age){
this.grander = grander;
this.age = age;
}
Person.prototype.plainProp = 'hi';
Person.prototype.objectProp = {'age':20};
var a = new Person();
var b = new Person();
//浅克隆
var c = new Animal('male',5);
var d = c;
d.grander = 'female';
//深克隆一
var e = new Animal('male',5);
var f = JSON.parse(JSON.stringify(e));
//深克隆二
var g = new Animal('male',{type:'older',age:5});
var h = deepclone(g);
h.age.type = 'younger';
//递归方法
function deepclone(object){
var result;
if(isObject(object)=='Object')
result = {};
else if (isObject(object)=='Array')
result = [];
else
return object;
for(var key in object){
var copy = object[key]
if(isObject(copy)=='Object')
result[key] = deepclone(copy);
else if(isObject(copy)=='Array')
result[key] = deepclone(copy);
else
result[key] = copy;
}
return result;
}
//判断对象,基本类型,数组
function isObject(object){
var result = Object.prototype.toString.call(object).slice(8,-1);
return result;
}
g.grander = 'female';
a.plainProp = 'hello';
a.objectProp.age = 100;
console.log(a.objectProp);//'100'
console.log(b.objectProp);//'100'----修改错误
//原型替换
a.objectProp= {'age':200};
console.log(a.plainProp);//'hello'
console.log(b.plainProp);//'hi'
console.log(a.objectProp);//'20'
console.log(b.objectProp);//'200'
b.objectProp.age = 300;
console.log(a.objectProp);//'20' ----原型替换
console.log(b.objectProp);//'300'
console.log(a.hasOwnProperty('plainProp'))//'true'
console.log(b.hasOwnProperty('objectProp'))//'false'
console.log('==============>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
console.log(c.grander)//'female'
console.log(d.grander)//'female'
console.log('==============>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
console.log(e.grander)//'male'
console.log(f.grander)//'female'
console.log('==============>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
console.log(g.age.type)//'older'
console.log(h.age.type)//'younger'
构造对象是发生了什么?
- 从上面的图示中可以看到,创建p1对象虽然使用的是Person构造函数,但是对象创建出来之后,这个p1对象其实已经与Person构造函数没有任何关系了,p1对象的[[ prototype ]]属性指向的是Person构造函数的原型对象。
- 如果使用new Person()创建多个对象,则多个对象都会同时指向Person构造函数的原型对象。
- 我们可以手动给这个原型对象添加属性和方法,那么p1,p2,p3…这些对象就会共享这些在原型中添加的属性和方法。
- 如果我们访问p1中的一个属性name,如果在p1对象中找到,则直接返回。如果p1对象中没有找到,则直接去p1对象的[[prototype]]属性指向的原型对象中查找,如果查找到则返回。(如果原型中也没有找到,则继续向上找原型的原型—原型链。 后面再讲)。
- 如果通过p1对象添加了一个属性name,则p1对象来说就屏蔽了原型中的属性name。 换句话说:在p1中就没有办法访问到原型的属性name了。
- 通过p1对象只能读取原型中的属性name的值,而不能修改原型中的属性name的值。 p1.name = “李四”; 并不是修改了原型中的值,而是在p1对象中给添加了一个属性name。