构造函数:
这样就是复制,很浪费资源塞
function person(name,age)
{
this.name=name;
this.age=age;
}
var person1=new person("nick",12);//作为构造函数
person1.constructor==person;
true
任何函数,只要通过new操作符来调用,那它就可以作为构造函数,不通过new来调用就是普通函数。
person("nick",12);//作为普通函数调用
原型模式:
prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
function person(){}
undefined
person.prototype.name="nick";
"nick"
person.prototype.age=23;
23
var person1=new person();
undefined
person1.name;
"nick"
所有实例的内置prototype都无法访问到,但可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。
person.prototype.isPrototypeOf(person1)
true
Object.getPrototypeOf(person1)
person {name: "nick", age: 23}
Object.getPrototypeOf(person1)==person.prototype
true
Object.getprototype()得到它是谁的prototype.
虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们在实例中添加了一个属性,二改属性与实例原型中的一个属性同名,那么我们就在实例中创建该属性,该属性将会屏蔽原型中的那个属性。
function person(){}
person.prototype.name="nick";
"nick"
person.prototype.age=23;
23
var person1=new person();
person1.name="gery"
"gery"
var person2=new person()
person1.name
"gery"
person2.name
"nick"
第二个person2.name为原型中的name,并没有被改变塞,但person1的name则被覆盖了塞。但是使用delete操作符则可以完全删除实例属性,从而让我们能够重新访问到原型中的属性。
delete person1.name;
true
person1.name
"nick"
hasOwnProperty()方法可以检测一个属性是否存在于实例中,还是存在于原型中,这个方法只在给定属性存在于对象实例中才回返回true。
person1.hasOwnProperty("name")
false
person1.name="grey";//person1重写name
"grey"
person1.hasOwnProperty("name");
true
前面错误由于name来自原型,后一个name来自实例,是true。
原型与in操作符
在单独使用in操作符时,in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。
"name" in person1
true
"name" in person
true
在使用for-in循环时,返回的是所有能够通过对象访问的,可枚举的属性,其中既包括存在于实例中的属性,也包括存在于原型重点属性。
Object.keys()和Object.getPropertyNme()都可以代替for-in循环
var key=Object.keys(person1);
undefined
key
["name", "age"]
var key=Object.getOwnPropertyNames(person1)
undefined
key
["name", "age"]
var key=Object.getOwnPropertyNames(person)
undefined
key
["length", "name", "arguments", "caller", "prototype"]
var key=Object.getOwnPropertyNames(person.prototype)
undefined
key
"constructor"
var key=Object.getOwnPropertyNames(person1.prototype)
var o={toString:function(){return "my object";}}
undefined
for(var prop in o)
{
if(prop=="toString")
{alert("found you");
}}
undefined
prop
"toString"
更简单的原型写法
function person(){}
undefined
person.prototype={
name:"nick",
age:12,
sayname:function()
{
alert(this.name);
}
}
person.prototype.sayname()
"nick"
but!每创建一个函数,就会同时创建它的prototype对象,这个对象会自动获得constructor属性,它指向原函数,而我们在这里使用的语法,本质上完全重写了默认的prototype对象,因此constructor属性页就变成了新对象的constructor属性(指向Object构造函数),不在指向函数。
friend instanceof Object
true
friend instanceof person
true
friend.constructor==person //不再指向person
false
friend.constructor==Object
true
故将constructor重新指向person就好啦!
function person(){}person.prototype={
constructor:person,//将constructor指向person
name:"nick",age:12,
sayname:function()
{alert(this.name);}}
friend.constructor==person
true
组合使用构造函数模式和原型模式
构造函数用于定义实例属性,原型模式用于定义方法和共享属性
function person(name,age){this.name=name,this.age=age}
undefined
person.prototype={constructor:person,sayname:function(){alert(this.name)}}
var person1=new person("jack",12);
undefined
person1.sayname()
"jack"