关于Javascript中通过实例对象修改原型对象属性值的问题

Javascript中的数据值有两大类:基本类型的数据值和引用类型的数据值。

基本类型的数据值有5种:null、undefined、number、boolean和string。

引用类型的数据值往大的说就1种,即Object类型。往细的说有:Object类型、Array类型、Date类型、Regexp类型、Function类型等。

当原型对象的属性值为基本类型的数据值时,通过实例对象修改属性值从而引起原型对象的属性值发生变化的情况不会发生。当原型对象的属性值为引用类型的数据值时,通过实例对象修改属性值就可能引起原型对象的属性值发生变化。下面举例说明。

例1:

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();
//没有改变原型的number属性,而是自己获得了number属性
animal1.number = 1000;
console.log(animal2.number);//very much

上例中通过构造函数Animal创建了两个实例对象,两个实例对象继承了同一个原型对象的属性。通过实例对象animal1重新设置了number属性,结果是实例对象animal1拥有了自己的number属性,没有改变原型对象的number属性值,实例对象animal2调用的number属性还是原型对象原来的number属性。

例2:

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"];
for (var i=0;i<animal2.fish.length;i++) {
  console.log(animal2.fish[i]);//shark,sardine,没有cold fish
 }
//通过实例对象animal3向fish属性中推入项,改变了原型对象的fish属性,因为实例对象中没有自己的fish属性
animal3.fish.push("voladao");
animal3.fish[0] = "fly fish"; for (var i=0;i<animal2.fish.length;i++) { console.log(animal2.fish[i]);//fly fish,sardine,voladao }

例2中实例对象animal1创建了自己的fish属性,没有改变原型对象的fish属性,所以实例对象animal2输出的还是原型对象的fish属性。

实例对象animal3没有自己的fish属性,但通过实例对象animal3向fish属性中推入了一项,并且改变了其中的第一项的值,这些改变都发生在了原型对象的fish属性上,所以实例对象animal2调用fish属性时,其属性值发生了变化。

例3:

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();
var animal4 = new Animal();
var animal5 = new Animal();
//改写了原型中的bird属性
animal1.bird.ability = "run";
console.log(animal2.bird.ability);//run
//创建animal3的bird属性,没有改变原型对象的bird属性
 animal3.bird = {
   eat: "fish"
 };
 console.log(animal4.bird.eat);//undifined
 console.log(animal3.bird.eat);//fish
 animal5.bird.home = "tree";
 console.log(animal4.bird.home);//tree

例3中通过实例对象animal1修改了bird属性的ability属性的值,实例对象animal1没有自己的bird属性,这个修改反映在了原型对象的bird属性上,实例对象animal2输出的bird.ability的值是改变后的值。

实例对象animal3创建了自己的bird属性,这没有改变原型对象的bird属性,所以实例对象4的bird.eat的值为undifined。

通过实例对象animal5添加了bird属性的home属性,实例对象animal5没有自己的bird属性,这个home属性添加到了原型对象的bird属性上,所以animal4的bird.home的值为tree。

至于其他的引用类型的数据值有没有以上特性,暂时还没有想到怎么验证,先这样吧。