js常用的几种创建对象的方式有:
{}
new Object()
- 使用字面量
- 工厂模式
- 构造函数模式(constructor)
- 原型模式(prototype)
- 构造函数+原型模式
还有一些不常用的方式,如动态原型,寄生构造函数,稳妥构造函数。
一、通过{}
创建对象
demo1: 01.newObj-1.html
<script>
'use strict'; //使用strict模式
/**
使用{}创建对象,等同于 new Object();
**/
var o = {};
o.name = 'jack';
o.age = 20;
o.sayName = function(){
alert(this.name);
}
alert(o.name+'-'+o.age);
o.sayName();
</script>
如果对象不用重复创建,这种方式是比较方便的。
二、通过new Object()
创建对象
demo2: 02.newObj-2.html
<script>
'use strict';
// 使用 new Object() 创建对象
var o = new Object();
o.name = "zhangsna";
o.sayName = function(){
alert(this.name);
}
o.sayName();
alert('o instanceof Object>>>>>>>>>>>'+(o instanceof Object));//true
alert("typeof o >>>>> "+typeof o);//object
</script>
三、使用字面量创建对象
对象字面变量是对象定义的一种简写形式,举个例子:
var person = {name: 'zhang', age:20}
, 这就是字面量形式,完全等价于var person = {}; person.name='zhang'; person.age=20;
。
小结:前面三种创建对象的方式存在2个问题:1.代码冗余; 2.对象中的方法不能共享,每个对象中的方法都是独立的。
四、使用工厂模式创建对象
这种方式是使用一个函数来创建对象,减少重复代码,解决了前面三种方式的代码冗余的问题,但是方法不能共享的问题还是存在。
demo4: 04.newObj-4.html
<script>
'use strict';
// 使用工厂模式创建对象
// 定义一个工厂方法
function createObject(name){
var o = new Object();
o.name = name;
o.sayName = function(){
alert(this.name);
};
return o;
}
var o1 = createObject('zhang');
var o2 = createObject('li');
//缺点:调用的还是不同的方法
//优点:解决了前面的代码重复的问题
alert(o1.sayName===o2.sayName);//false
</script>
五、通过构造函数创建对象
所谓构造函数,也是普通的函数,不过约定俗成,构造函数的名称首字母大写,普通函数的首字母小写。通过new 构造函数
来创建对象。
demo5:05.newObj-5.html
<script>
'use strict';
/**
* 构造函数模式创建对象
**/
function Person(name){
this.name = name;
this.sayName = function(){
alert(this.name);
};
}
var p1 = new Person('zhang');
var p2 = new Person('li');
p1.sayName();
p2.sayName();
alert(p1.constructor === p2.constructor);//true
alert(p1.constructor === Person);//true
alert(typeof(p1));//object
alert(p1 instanceof Object); //true
alert(p2 instanceof Object); //trueb
alert(p1.sayName===p2.sayName);//false
</script>
内存模型:
通过内存模型,可以发现,sayName
函数是独立存在于每个对象的,所以p1.sayName===p2.sayName
结果为false
,还是没有解决方法不能共享的问题。
六、通过原型模式创建对象
每个方法中都有一个原型(prototype
),每个原型都有一个构造器(constructor
),构造器又指向这个方法。
举个例子:
function Animal(){}
alert(Animal.prototype.constructor==Animal);//true
原型创建对象:
demo6:06.newObj-6.html
<script>
'use strict';
/*
* 原型模式创建对象
*/
function Animal() { }
Animal.prototype.name = 'animal';
Animal.prototype.sayName = function () { alert(this.name); };
var a1 = new Animal();
var a2 = new Animal();
a1.sayName();
alert(a1.sayName === a2.sayName);//true
alert(Animal.prototype.constructor);//function Animal(){}
alert(Animal.prototype.constructor==Animal);//true
</script>
通过原型创建对象,把属性和方法绑定到prototype
上,通过这种方式创建对象,方法是共享的,每个对象调用的是同一个方法。
内存模型:
如果往新建的对象中加入属性,那么这个属性是放在对象中,如果存在与原型同名的属性,也不会改变原型的值。但是访问这个属性,拿到的是对象的值。
访问的顺序:对象本身>构造函数的prototype
如果对象中没有该属性,则去访问prototype,如果prototype中没有,继续访问父类,直到Object,如果都没有找到,返回undefined
demo7: https://github.com/mkh10086/javascript-demo/blob/master/10-mashibing/07.newObj-7.html
<script>
'use strict';
/*
* 原型模式创建对象
*/
function Animal() { }
Animal.prototype.name = 'animal';
Animal.prototype.sayName = function () { alert(this.name); };
var a1 = new Animal();
var a2 = new Animal();
a1.sayName();
alert(a1.sayName === a2.sayName);//true
alert(Animal.prototype.constructor);//function Animal(){}
//修改a2.name,a1的name不会变
a2.name = 'dog';
a2.sayName();//dog
a1.sayName();//animal
</script>
内存模型:
这种方式创建的对象会存在问题,假如原型中包含有引用类型的属性,那么如果某个对象修改了该属性的值,所有的该原型创建的对象访问的值都会改变。
demo8: 08.newObj-8.html
<script>
'use strict';
//原型模式2
//存在的问题:如果原型中含有引用类型
function Animal (){}
Animal.prototype = {
name: 'animal',
friends: ['dog','cat'],
sayName: function(){
alert(this.name);
}
};
var a1 = new Animal();
var a2 = new Animal();
a2.friends.push('snake');
alert(a2.friends);//[dog,cat,snake]
alert(a1.friends);//[dog,cat,snake]
</script>
内存模型:
七、通过原型+构造函数的方式创建对象
这种方式结合了上面两种方式,解决了代码冗余,方法不能共享,引用类型改变值的问题。
demo9: 09.newObje-9.html
<script>
'use strict';
function Animal(name){
this.name = name;
this.friends = ['dog','cat'];
}
Animal.prototype.sayName = function(){
alert(this.name);
};
var a1 = new Animal('d');
var a2 = new Animal('c');
a1.friends.push('snake');
alert(a1.friends);//[dog,cat,snake]
alert(a2.friends);//[dog,cat]
</script>
内存模型: