Skip to content

Commit ffb1926

Browse files
committed
commit
1 parent 106e6e3 commit ffb1926

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

chapter3.markdown

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,93 @@ JavaScript中没有类的概念,这给JavaScript带来了极大的灵活性,
8686

8787
### 获得对象的构造器
8888

89+
创建实例对象时能用对象直接量就不要使用new Object()构造函数,但有时你希望能继承别人写的代码,这时就需要了解构造函数的一个“特性”(也是不使用它的另一个原因),就是Object()构造函数可以接收参数,通过参数的设置可以把实例对象的创建委托给另一个内置构造函数,并返回另外一个实例对象,而这往往不是你所希望的。
8990

91+
下面的示例代码中展示了给new Object()传入不同的参数:数字、字符串和布尔值,最终得到的对象都是由不同的构造函数生成的:
92+
93+
// Warning: antipatterns ahead
94+
95+
// an empty object
96+
var o = new Object();
97+
console.log(o.constructor === Object); // true
98+
99+
// a number object
100+
var o = new Object(1);
101+
console.log(o.constructor === Number); // true
102+
console.log(o.toFixed(2)); // "1.00"
103+
104+
// a string object
105+
var o = new Object("I am a string");
106+
console.log(o.constructor === String); // true
107+
// normal objects don't have a substring()
108+
// method but string objects do
109+
console.log(typeof o.substring); // "function"
110+
111+
// a boolean object
112+
var o = new Object(true);
113+
console.log(o.constructor === Boolean); // true
114+
115+
Object()构造函数的这种特性会导致一些意想不到的结果,特别是当参数不确定的时候。最后再次提醒不要使用new Object(),尽可能的使用对象直接量来创建实例对象。
116+
117+
## 自定义构造函数
118+
119+
除了对象直接量和内置构造函数之外,你也可以通过自定义的构造函数来创建实例对象,正如下面的代码所示:
120+
121+
var adam = new Person("Adam");
122+
adam.say(); // "I am Adam"
123+
124+
这里用了“类”Person创建了实例,这种写法看起来很像Java中的实例创建。两者的语法的确非常接近,但实际上JavaScript中没有类的概念,Person是一个函数。
125+
126+
Person构造函数是如何定义的呢?看下面的代码:
127+
128+
var Person = function (name) {
129+
this.name = name;
130+
this.say = function () {
131+
return "I am " + this.name;
132+
};
133+
};
134+
135+
当你通过关键字new来调用这个构造函数时,函数体内将发生这些事情:
136+
137+
- 创建一个空对象,将它的引用赋给this,继承函数的原型。
138+
- 通过this将属性和方法添加至这个对象
139+
- 最后返回this指向的新对象(如果没有手动返回其他的对象)
140+
141+
用代码表示这个过程如下:
142+
143+
var Person = function (name) {
144+
// create a new object
145+
// using the object literal
146+
// var this = {};
147+
148+
// add properties and methods
149+
this.name = name;
150+
this.say = function () {
151+
return "I am " + this.name;
152+
};
153+
154+
//return this;
155+
};
156+
157+
正如这段代码所示,say()方法添加至this中,结果是,不论何时调用new Person(),在内存中都会创建一个新函数(译注:所有Person的实例对象中的方法都是独占一块内存的)。显然这是效率很低的,因为所有实例的say()方法是一模一样的,因此没有必要“拷贝”多份。最好的办法是将方法添加至Person的原型中。
158+
159+
Person.prototype.say = function () {
160+
return "I am " + this.name;
161+
};
162+
163+
我们将会在下一章里详细讨论原型和继承。现在只要记住将需要重用的成员和方法放在原型里即可。
164+
165+
关于构造函数的内部工作机制也会在后续章节中有更细致的讨论。这里我们只做概要的介绍。刚才提到,构造函数执行的时候,首先创建一个新对象,并将它的引用赋给this:
166+
167+
// var this = {};
168+
169+
事实并不完全是这样,因为“空”对象并不是真的空,这个对象继承了Person的原型,看起来更像:
170+
171+
// var this = Object.create(Person.prototype);
172+
173+
在后续章节会进一步讨论Object.create()。
174+
175+
### 构造函数的返回值
90176

91177

92178

0 commit comments

Comments
 (0)