您的位置:首页 > Web前端 > JavaScript

【javascript笔记】关于函数的构造函数和prototype<四>

2014-11-08 14:40 483 查看
一,构造函数创建对象

function Person(name,age,job){ 
	this.name=name;
	this.age=age;
	this.job=job;
	this.getName=function(){ 
		return this.name;
	}
	this.getAge=function(){ 
		return this.age
	}
	this.getJob=function(){ 
		return this.job;
	}
}

//请看这里 咱们新建一个对象  
var person1=new Person('nicolas',29,'software engineer');
var person2=new Person('jack',29,'software engineer');		
person1.getName(); //	nicolas
person2.getName();// jack

到此为止 咱们做一个实验:alert(person1.sayName==person2.sayName) //输出为false.

不是同一个函数对象这似乎很许多强类型语言 比如java和c#类似 声明类的属性 然后设置getset方法去调用

但是 为每一个对象都去初始化这样 “执行同一个动作”的函数对象 是否合乎情理呢,这样我们就自然而然想到了j

ava中的静态关键字,

我们姑且可以将prototype理解为静态的成员或者方法,new的对象是共享的,这样我们就会节约内存?

二,再来看原型模式创建对象

function Person(){ 
  }
Person.prototype.name='nicolas';
Person.prototype.age=29;
Person.prototype.job='software engineer';
Person.prototype.sayName=function(){ 
return this.name
}
//请看这了 咱们还是新建两个对象
  var person1=new Person();
  var person2=new Person();
  person1.getName();//nicolas
  person2.getName();//nicolas</span>
到此为止,咱们仍旧做这个同上的实验 alert(person1.sayName==person2.SayName);//输出为true,是同一个对象重点(理解不到也没关系,楼主也是有点晕)构造函数,原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针 ,而每个实力都包含一个指向原型对象的内部指针。现在我们以第二个声明函数的方式来做个例子:

var person1=new Person();
    var person2=new Person();
    person1.name="Jack";
    alert(person1.name);//Jack
    alert(person2.name);//nicolas


这时候大家就会奇怪,不是说原型里面都是共享的吗?为什么person2输出的还是原型设置的nicolas 而不是Jack;请注意:这里我们为person1的name设置了新的值后; "如果我们在实例中添加了一个属性,并且该属性与实例原型中的一个实例重名 ,那我们就是在实例中创建了该属性,换句话说就是:person1.name='Jack';这一句代码表示了这个name是属于实例的属性.它会阻止我们去访问实例的原型中的nicolas";当然我们也可以通过代码delete
person1.name; 去删除person1.name这个实例属性,执行了这局代码后:

alert(person1.name);//nicolas 原型属性

javascript里面有很多判断属性是属于实例或者原型的,请大家自行搜索。

三,更加简单的原型语法:以字面量形式创建原型对象

function Person(){ }
    Person.prototype={ 
    	name="nicolas",
    	age=29,
    	job="software engineer",
    	getName=function(){ 
    		return this.name;
    	}
    }</span>
第二大点中说过,每创建一个函数就会同时创建他的prototype对象,这个对象也会自动获得constructor属性(指向构造函数的指针);但是这里constructor属性不再指向Person了,这里我们使用的字面量声明方式本质上完全重写了默认的prototype对象,指向构造函数的指针不会指向原来Person,而是Object.

//如果原型指向构造函数的指针真的这么重要,请像下面这样声明:
	function Person(){ }
        Person.prototype={ 
    	constructor:Person,
    	name:"nicolas",
    	age:29,
    	job:"software engineer",
    	getName:function(){ 
    		return this.name;
    	}

    }
		
	//但是这种方式重新设置constructor属性会导致它的[Enumerable]属性设置为true.默认情况下原生的constructor属性是不可枚举的, 
	//因此如果你是用兼容ECMAScript5的javascript引擎 请像下面这样声明:
function Person(){ }
    Person.prototype={ 
    	name:"nicolas",
    	age:29,
    	job:"software engineer",
    	getName:function(){ 
    		return this.name;
    	}

    }
    Object.defineProperty(Person.prototype,"constructor",{ 
    	enumerable:false,
    	value:Person
    })
四, 在第三点中提到了用表达式方式声明prototype会或重写默认的prototype对象,这就引出了这一个话题:原型的动态性

<span style="font-size:12px;"> var friend=new Person();
     Person.prototype.sayHello=function(){ 
     	alert('Hello~')
     }
     friend.sayHello();//不会报错

     //但是 若是这样
     function Person(){}
     var friend=new Person();
     Person.prototype={ 
     		...something
     		sayHello:function(){ 
     		alert('Hello~')
     		}
     }
     friend.sayHello();//error</span>
用表达式这种方法添加sayHello(),重写了整个prototype 但是当下的friend对象仍然是指向原来的原型,当我们原型整个修改就相当于把原型修改为另外一个对象了,切断了构造函数与最初原型之间的联系。请记住 实例中的指针仅仅指向原型,而不指向构造函数。 相当于当前friend指向的原型 和我们重新写的没有任何关系~

五,原型存在的问题

最重要的问题就是 共享的属性若是引用类型,只要任何实例一改动,原型里面的内容也会改动;

function Person(){} 
     Person.prototype={  
     	name:"nicolas",
     	job:'software engineer',
     	age;29,
     	friends:['sheldon','Lenard']
     };
     var person1=new Person();
     var person2=new Person();

     person1.friends.push('Nianlu');
     alert(person1.friends);// sheldon,Lenard,Nianlu
     alert(person2.friends);// sheldon,Lenard,Nianlu

     //再看,他们引用的是否是同一个数组
     alert(person1.friends==person2.friends) //true


六,组合使用构造函数和原型模式

//既然两种模式各有优缺点,我们就把两者结合到一起,请看下面的例子
     function Person(name,job,age){ 
     		this.name=name;
     		this.job=job;
     		this.age=age;
     		this.friends=['Sheldon','Lenard'];
     }
     Person.prototype={ 
     		constructor:Person,
     		sayHello:function(){ 
     			alert('Hello~');
     		}
     }
     var person1=new Person('nicolas','software engineer',29);
     var person1=new Person('jack','software engineer',29);
     person1.friends.push('Kimkadasion');
     
     alert(person1.friends);// sheldon,Lenard,Kimkadasion
     alert(person2.friends);// sheldon,Lenard

     alert(person1.friends==person2.friends) //false
     alert(person1.sayHello==person2.sayHello) //true


结束~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐