@@ -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