Javascript中的数据值有两大类:基本类型的数据值 ,引用类型的数据值。
基本类型的数据值:null、undefined、number、boolean和string。
引用类型的数据值:Object (Object类型、Array类型、Date类型、Regexp类型、Function类型)。
当原型对象的属性值为基本类型的数据值时,通过实例对象修改属性值从而引起原型对象的属性值发生变化的情况不会发生。
当原型对象属性值为引用类型的数据时,通过实例对象修改属性值从而引起原型对象的属性值发生变化的情况会发生。
基本类型的数据:
function Supert(){
this.colors="红色的"
}
var person1= new Supert();
var person2= new Supert();
person1.colors="白色的";
console.log(person2.colors);//红色的
通过构造函数,创建了两个实例对象,两个实例对象继承了同一个原型对象的属性。通过实例对象person1重新设置了Supert属性,结果是实例对象person1拥有了自己的colors属性,没有改变原型对象的colors属性值,实例对象person2调用的colors属性还是原型对象原来的colors属性。
引用类型的数据:
function Animal() {}
Animal.prototype = {
constructor: Animal,
number: "very much",
fish: ["shark","sardine"],
bird:{
ability: "fly",
feature: "feather"
}
};
var animal1 = new Animal();
var animal2 = new Animal();
var animal3 = new Animal();
//没有改写原型中的fish属性,此时animal1实例对象中有了自己的fish属性,向其自己的fish属性中推入和弹出项不会改变原型的fish属性。
animal1.fish = ["cold fish"];
//通过实例对象animal3向fish属性中推入项,改变了原型对象的fish属性,因为实例对象中没有自己的fish属性
animal3.fish.push("voladao");
实例对象animal1创建了自己的fish属性,没有改变原型对象的fish属性,所以实例对象animal2输出的还是原型对象的fish属性。
实例对象animal3没有自己的fish属性,但通过实例对象animal3向fish属性中推入了一项,并且改变了其中的第一项的值,这些改变都发生在了原型对象的fish属性上,所以实例对象animal2调用fish属性时,其属性值发生了变化。
使用赋值语句("=")修改实例属性时,不会修改原型对象的值的原因:
为什么通过person1.colors
能获取到原型链上的colors属性,但是通过person1.colors = "白色"
却不能修改原型链上的属性而是添加新属性呢?
- 原型链的作用是为对象提供默认值,即当对象自身不存在某属性的时候,这个属性应该表现出的默认值。为这个属性赋值的时候,不应该通过“改变默认值”(修改原型链上的属性)来做到,而应该通过创建一个新的值来掩盖(shaow)默认值(默认值仍然存在,只是不再表现出来)。这样做的一个好处是,你以后可以
delete person1.colors
,然后person1.colors
就会再次表现出默认值。假设不采用这个方案,而是通过“改变默认值”,那么原来的默认值就会丢失,delete person1.colors
不会起作用(delete操作符只会删除对象自身的属性)。 - 多个对象可能共享同一个原型对象,如果对其中一个对象的属性赋值就可以改变原型对象的属性,那么"="操作符会变得非常危险,因为这会影响到共享这个原型的所有对象
具体可查看AssignmentExpression:LeftHandSideExpression=AssignmentExpression表达式在运行时的求值算法