var Person =new Object();
Person.name = 'Jason';Person.age = 21;复制代码
var Person={}; //等同于var Person =new Object();
var Person={
name:"Jason",
age:21
}复制代码
对象字面量是对象定义的一种简写形式,第一种和第二种建立形式的缺点就是:他们用同一个接口建立不少对象和,会产生大量的重复代码,若是你有500个对象,那么你就要输入500次不少相同的代码。bash
function createPerson(name,age,job)
{ var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function()
{ alert(this.name); };
return o;
}
var person1 = createPerson('Nike',29,'teacher');
var person2 = createPerson('Arvin',20,'student');复制代码
在使用工厂模式建立对象的时候,咱们均可以注意到,在createPerson函数中,返回的是一个对象。那么咱们就没法判断返回的对象到底是一个什么样的类型。因而就出现了第四种建立对象的模式函数
function Person(name,age,job)
{ this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){ alert(this.name); };
}
var person1 = new Person('Nike',29,'teacher');
var person2 = new Person('Arvin',20,'student');复制代码
对比ui
工厂模式,咱们能够发现如下区别:this
1.没有显示地建立对象spa
2.直接将属性和方法赋给了this对象prototype
3.没有return语句code
4.终于能够识别的对象的类型。对于检测对象类型,咱们应该使用instanceof操做符,咱们来进行自主检测对象
alert(person1 instanceof Object);//turealert
(person1 instanceof Person);//turealert
(person2 instanceof Object);//turealert
(person2 instanceof Object);//ture复制代码
同时咱们也应该明白,按照惯例,构造函数始终要应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。接口
1 建立一个新的对象(遇到new 的时候)ip
2 将构造函数的做用域赋给新的对象(所以this就指向这个对象)
3 执行构造函数中的代码(为这个对象添加属性)
4 返回新对象
那么构造函数确实挺好用的,可是它也有它的缺点:
每一个对象里面都有公用的函数,意味着每次建立都会穿件这个函数,所以能够这个函数放到外面,可是会污染全局做用域。
就是每一个方法都要在每一个实例上从新建立一遍,方法指的就是咱们在对象里面定义的函数。若是方法的数量不少,就会占用不少没必要要的内存。因而出现了第五种建立对象的方法
function Person(){}
Person.prototype.name = 'Nike';
Person.prototype.age = 20;
Person.prototype.jbo = 'teacher';
Person.prototype.sayName = function(){ alert(this.name);};
var person1 = new Person();person1.sayName();复制代码
使用原型建立对象的方式,可让全部对象实例共享它所包含的属性和方法。
若是是使用原型建立对象模式,请看下面代码:
function Person(){}
Person.prototype.name = 'Nike';
Person.prototype.age = 20;
Person.prototype.jbo = 'teacher';
Person.prototype.sayName = function()
{ alert(this.name);};
var person1 = new Person();
var person2 = new Person();
person1.name ='Greg';alert(person1.name);
//'Greg' --来自实例alert(person2.name); //'Nike' --来自原型复制代码
前面的例子中,每添加一个属性和方法都要敲一遍Person.prototype。为减小没必要要的输入,从视觉上更好封装原型的功能。常见的作法:
function Person(){}
Person.prototype={
name:"NIke",
age:11,
sayName:function(){
alert(this.name);
}
};复制代码
在上面的代码中,咱们将Person.prototype设置为等于一个以对象字面量形式建立新对象,最终结果相同,但有一个例外:constructor属性不在指向Person了。
咱们所建立的每个函数,解析器都会向函数中添加一个属性prototype这个属性对应着一个对象,这个对象就是咱们所谓的原型对象。
若是函数做为普通函数调用,prototype没有任何做用
当函数以构造函数调用时,它所建立的对象中都会有一个隐含的属性指向该构造函数的原型对象,咱们能够经过__proto__来访问该属性
原型对象就至关于一个公共的区域,全部同一个类的实例均可以访问到这个原型对象,咱们将对象中共有的内容,统一设置到原型对象中,
当咱们访问对象的一个属性或方法时,它会先在对象自身中寻找,若是有则直接使用,若是没有则去原型对象寻找。
函数名.a=123;//只会添加到函数名该类的里面
函数名.prototype.a=123//会添加到原型对象里面复制代码
使用 in 检查对象中是否含有某个属性时,若是对象中没有可是原型中有,也会返回true
console.log("属性" in 对象名)复制代码
使用对象的hasOwnProperty()来检查对象自身(实例)中是否存在该属性,使用该方法只有当对象自身含有属性时,才会返回true
对象名.hasOwnProperty("属性名")复制代码
原型对象也是对象,因此它也有原型:
当咱们使用一个对象的属性或者方法时,会在自身寻找,
自身若是有,则直接使用
若是没有则去原型对象中寻找,若是原型对象中有,则使用。
若是没有则去原型的原型对象去寻找,直到object对象的原型,object对象的原型没有原型,若是在object中依然没有找到,则返回undefined
当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性。
这时候咱们就可使用构造函数模式与原型模式结合的方式,构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性
function Person(name,age,job)
{ this.name =name;
this.age = age;
this.job = job;}
Person.prototype = {
constructor:Person,
sayName: function()
{ alert(this.name); };
}
var person1 = new Person('Nike',20,'teacher');复制代码
建立自定义类型的最多见方式,就是组合使用构造函数模式和原型模式
实例属性都是在构造函数中定义的,而全部实例共享的属性constructor和方法sayName()则是在原型中定义。这种模式是ECMAScript中使用最普遍,承认度最高的一种建立自定义类型的方法,能够说这是用来定义引用类型的一种默认模式。