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

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

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

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


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