js对象的创建
一、通过对象直接量来创建
var emptyt={}; //相当于var empty=new Object;
//如果属性名中包含空格、连字符(-)、还有关键字,保留字时,要用字符串表示
var book={
“main title”:“javascript”,
“sub-title”:“The Definitive Guide”, //属性名包含连字符
“for”:“all audiences”, //属性名包含保留字
author:{
firstname:“David”,
surname:“Flanagan”,
}
}
二、通过new+构造函数创建对象
构造函数可以是js中的内置构造函数和自定义的构造函数
var o=new Object();//创建一个空对象 和{}一样
var a=new Array();//创建一个空数组和[]一样
var d=new Date();//创建一个表示当前时间的对象
var r=new RegExp(‘js’);//创建一个可以进行模式匹配的RegExp对象
三、Object.create()创建对象
Object.creat()是一个静态函数,不是提供给某个对象调用的方法,使用时,需要传递原型对象(及要继承的对象),第二个参数可选,用以对对象的属性进行进一步描述。
var o1=Object.create({x:1,y:2}); //o1继承了属性x和y
可以通过传入参数null创建一个没有原型对象的新对象,通过这种方式创建的对象不继承任何东西
var o2=Object.create(null);//o2不继承任何属性和方法
如果想创建一个普通的空对象(比如通过{ }或者new Object()创建的对象);需要传入Object.prototype;
var o3=Object.create(Object.prototype); //o3和{}、new Object一样
四、工厂模式
工厂模式非常直观,将创建对象的过程抽象为一个函数,用函数封装以特定接口创建对象的细节,通俗的讲,工厂模式就是将创建对象的语句放在一个函数里面,通过传入参数来创建特定对象,最后返回创建的对象,工厂模式虽然可以创建多个相似的对象,但是不能解决对象标识的问题,即知道一个对象的类型。
function createStudent(name,sex,grade)
{
var o=new Object( );
o.name=name;
o.sex=sex;
o.grade=grade;
o.sayName=function()
{
console.log(this.name)
}
return o;
}
var s1=createStudent(“david”,“女”,“15”);
五、构造函数模式
像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境。此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。
function Student(name,sex,grade)
{
this.name=name;
this.sex=sex;
this.grade=grade;
this.sayName=function()
{
console.log(this.name);
}
}
var s1=new Student(“we”,“女”,“17”);
注意:构造函数的首写字母必须大写,以便与普通函数区分开来。
此外要注意,要创建Student的实例,必须使用new操作符,创建的实例对象将有一个constructor(构造器属性),指向Person构造函数。
调用构造函数创建对象主要经历了下面几个步骤:
1、创建一个新对象;
2、把构造函数的作用域赋给新的对象(因此this就是指向新的对象实例);
3、执行构造函数中的代码;
4、返回新对象;
构赞函数的缺点:
每个方法都要在每个实例上面创建一遍,函数即是对象,因此每定义一个函数,也就实例化了一个对象。所以调用同一个构造函数所创建的不同实例对象中的方法是不相等的。
var s3 = new Student('唐僧','male',3);
var s4 = new Student('白骨精','female',4);
s3.sayName();
s4.sayName();
console.log(s3.sayName == s4.sayName); //结果为false 所以两个方法是两个不同的方法
六、原型模式
js中,每个对象都有一个prototype属性,原型对象,原型对象包含了可以由特定类型的所有实例对象的共享的属性和方法。
使用原型模型可以让所有的实例对象共享原型对象中的属性和方法。
function Student_1(){
}
Student_1.prototype={
name:“wangyue”,
sex:“女”,
class:5,
sayName:function()
{
console.log(this.name)
}
}
var s1=new Student_1();
var s2=new Student_2();
console.log(s1.sayName==s2.sayName);
了解原型后可以继续在实例对象上面添加属性和方法;
s1.name=“john”;
console.log(s1.name);打印出来是john;
当要读取某个对象的属性时,都会执行一次搜索,搜索首先从对象实例本身开始,如果在实例中找到了这个属性,则搜索结束,返回实例属性的值;若实例上没有找到,则继续向对象的原型对象延伸,搜索对象的原型对象,若在原型对象上找到了,则返回原型上相应属性的值,若没有找到,则返回undefined。因此,实例对象属性会覆盖原型对象上的同名属性,所以上面第二行代码输出的是John。
Object.getPrototypeOf(object)方法返回参数对象的原型对象。
Object.keys(object)方法返回对象上可枚举的实例属性。
Student_1.prototype.friends = ['aa','bb'];
console.log('s6的朋友' + s6.friends);
s5.friends.push('cc');
console.log('s5的朋友' + s5.friends);
console.log('s6的朋友' + s6.friends);
问题来了,我们只想改变s5的朋友列表,但由于原型模式的共享本质,s6的朋友列表也随之改变了。因此,很少单独使用原型模式。
七、组合使用构造函数和原型模式
构造函数模式用于定义实例属性,原型模式则用于定义方法和共享的属性。这种混合模式不仅支持向构造函数传入参数,还最大限度地节约了内存,可谓是集两模式之长。示例代码如下:
function Student(name,sex,grade){
this.name = name;
this.sex = sex;
this.grade = grade;
}
Student.prototype.sayName = function(){
console.log(this.name);
}
Student.prototype.school = 'Joooh school';
除了以上几种常见的模式外,批量创建对象的方式还有
动态原型模式:仅在第一次调用构造函数时,将方法赋给原型对象的相应属性,其他示例的处理方式同构造函数模式
寄生构造函数模式:仅仅封装创建对象的代码,然后再返回新创建的对象,仍使用new操作符调用
稳妥构造函数模式:没有公共属性,只有私有变量和方法,以及一些get/set方法,用以处理私有变量。