要点
- 需要创建少量对象时,适合使用对象字面量。
需要创建大量类似的对象时,适合使用构造函数(可创建相同属性和方法的一系列对象,通过向构造函数传递实参指定其属性) - 根据约定,将构造函数名的首字母大写、构造函数实参与属性同名
- 在构造函数中,使用this来访问正在创建的对象
- 要创建对象,可使用运算符
new
调用构造函数(由此得到一个新的对象实例) - 使用new来调用构造函数时,将新建一个空对象,并在构造函数中将其赋给this,最终自动返回创建的新对象。
- 创建和返回新对象的工作都是
new
完成的,构造函数只负责为新对象赋值 - 如果忘记使用new关键字,将不会创建任何对象,导致难以调试的错误。(如果用构造函数创建新对象,但在试图引用这些对象时发现其是
undefined
,则检查是否忘记了使用new) - 如果构造函数有很多形参,应考虑将它们合并为单个对象形参。
- 要判断对象是否是使用特定构造函数创建的,可使用运算符instanceof
如何创建对象
对象字面量
- 用于小规模创建对象:创建一次性的简单对象,逐个指定对象的所有属性
- 优点:更简洁,更具表达力
var dog={
name:"Fido",
brees:"Mixed",
weight:38
bark : function() {//添加方法
alert(this.name + " says Woof!");
}
};
对象构造函数
- 用于大规模创建基本结构相同的对象(像饼干模具一样创建对象)
优点:可重用代码,还可确保对象的一致性(所得对象包含相同的方法和属性) - 牢记,对象构造函数和函数关系密切但不完全等同:从代码看,构造函数很像返回对象的函数,但并非这么简单
通过对象构造函数创建对象,分为两步:定义一个构造函数,调用构造函数(使用new
运算符)并创建对象
下面是一个对象构造函数,它类似函数,同时在语法上又有点像对象
- 约定:给构造函数命名时,首字母大写,从而区分出常规函数和构造函数
- 约定:形参名和属性名相同,从而使代码更清晰
function Dog(name, breed, weight) {//形参用于存储要赋给对象的属性值
//与大多函数不同,没有使用局部变量,而是使用关键字this
this.name = name;
this.breed = breed;//注意,这里是分号(赋值语句),而非逗号
this.weight = weight;
this.bark = function() {//添加对象方法的代码与之前相同,区别在于左侧为this.bark
alert(this.name + " says Woof!");
};
//注意,构造函数没有返回任何值
}
//用对象构造函数创建新对象,使用了运算符new,new返回指向新对象的引用
var fido = new Dog("Fido", "Mixed", 38);
//变量fido的值为:指向新小狗对象的引用(fido的类型为object)
注意这里的两个this的区别:
function Dog(name, breed, weight) {//形参用于存储要赋给对象的属性值 ... this.bark = function() { alert(this.name + " says Woof!"); }; ...
左边的this:构造函数中的this,(被设置为)指向正在创建的新对象,用来给新对象的属性赋值。因此,构造函数中,所有左侧的this代码针对的都是这个新对象。
右边的this:方法体中使用this,对象创建后,在某个具体对象的方法被调用时,this(被设置为)指向其方法被调用的对象。因此,在方法中,this总是表示其方法被调用的对象
通过对象构造函数创建对象:务必搭配关键字new
调用对象构造函数创建对象时,要搭配关键字new
var fido = new Dog("Fido", "Mixed", 38);
//变量fido的值为:指向新小狗对象的引用(fido的类型为object)
关键字new
是一个运算符,搭配构造函数使用,从而创建对象
运算符对操作数进行操作。
new
这种运算符只操作一种操作数:函数调用
关键字new
的工作原理
new
创建一个新对象,并设置构造函函的函数体内的关键字this指向新对象,执行构造函数中的语句,最后返回创建的新对象:
-
new
创建一个新的空对象 -
接下来,new设置this,使其指向这个新对象
ps.this
存储了一个引用,指向代码当前处理的对象 -
设置this后,调用构造函数
Dog
,并传递实参"Fido"、"Mixed"和38 -
执行函数,
Dog
给this对象的属性赋值。 -
构造函数函数执行完毕,运算符
new
自动返回this
(指向新创建的对象的引用)
指向新对象的引用被返回后,我们将其赋给变量fido(fido的类型为object)
不使用关键字new
的后果
由上,创建和返回新对象的工作都是new
完成的,构造函数只负责为新对象赋值
如果不使用关键字new
,直接调用对象构造函数,将导致:
- 由于构造函数没有返回值,将得到
undefined
- JavaScript将认为:构造函数的函数体中出现的
this
指向全局对象,即存储全局变量的顶级对象(在浏览器中为window
对象)
对象构造函数与常规函数的区别
问:也就是说,构造函数与常规函数没什么两样,只是前者给this对象的属性赋值?
答:如果说的是计算方面,答案是肯定的。
常规函数能做的,构造函数都可以做。
但有一件事情不能做:不能从构造函数中返回值,准确地说,构造函数必须返回新创建的对象,即返回this(指向新创建的对象的引用),这个工作由new自动完成
问: 创建对象时,使用构造函数或对象字面量没什么两样,对吗?
答:在不涉及原型式继承的更高级对象设计时,是这样的(之后将看到,使用构造函数,可以构建原型、通过原型创建对象)
问:为何需要使用new来创建对象?为何不在常规函数中(使用对象字面量)创建并返回对象吗?
答:两者都能创建对象,但使用new时会执行一些额外的操作,这将在运算符new的工作原理中介绍