基本概念

首先要明确和构造函数相关的基本概念,不要觉得概念定义这些都不重要,只要能自己能理解就ok,有时候分不清这些会让自己显得很不专业。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var Person = function(){
// age,showAge: 分别称为实例属性,实例方法(参考 《JavaScript高级程序设计v3》中的翻译)
// 因为这样定义的属性和方法,所有实例都会独立copy一份
this.age = 20;
this.showAge = function(){
alert(this.age);
}
// _foo,_foo2: 私有属性和方法,开头下划线是比较常见的约定
var _foo = 'foo';
function _foo2(){
//...
}
}
// job,showJob: 原型属性和方法
Person.prototype = {
job: 'FE',
showJob: function(){
alert(this.job);
}
}
//bar,bar2: 静态属性和方法
Person.bar = 'baz';
Person.bar2 = function(){
//...
}

以上命名都是传统静态语言中的命名对应到js中的叫法。

返回值问题

正常情况下,使用构造函数时是不会使用return语句的,但是如果不小心或者刻意加入return语句,会怎样呢?直接上实验结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//没有返回值
function Test0(){
this.name='test0';
}
var test0=new Test0;
alert(test0); //输出[Object]
alert(test0.name); //输出test0
//return 一个对象字面量
function Test(){
this.name='test';
return {}; // 返回对象字面量
}
var test=new Test();
alert(test); //输出[Object]
alert(test.name); //输出undefined,说明构造函数创建的对象是返回的空{},this指向未生效。
//return 一个对象字面量
function Test1(){
this.name='test';
return []; // 返回对象字面量
}
var test1=new Test1();
alert(test1); //输出[]
alert(test1.name); //输出undefined,说明构造函数创建的对象是返回的空[],this指向未生效。
//return 一个字符串对象
function Test2(){
this.name='test';
return new String('123'); // 返回字符串对象
}
var test2=new Test2();
alert(test2); //输出123
alert(test2.name); //输出undefined,说明构造函数创建的对象是字符串对象
//return 一个原始类型字符串
function Test3(){
this.name='test2';
return '123';// 返回字符串对象
}
var test3=new Test3();
alert(test3); //输出[Object]
alert(test3.name); //输出test0

总结就是,如果返回值是引用类型数据,则使用返回值,否则使用正常构造函数创建绑定流程,return new String('123')这种形式生成的其实也是object(可使用typeof new String()验证)。

至于为什么是这样的表现,只能说规范是这么定的,说不准以后就改了。

new关键字

new 关键字究竟干了什么?结合上面梳理的基本概念来理解,new 大体上干了三件事:

1
2
3
4
5
6
var obj = {}; //创建一个空对象
obj.__proto__ == Person.prototype; //构造函数的原型对象指向obj.为的是obj能继承原型属性或方法。
Person.call(obj). //将Person的this指向为obj,并执行构造函数,为的是obj能继承实例属性或方法。

之前就看到过相关博文的分析,然而很快就忘了,记得不够深刻。。。究其原因,还是对构造函数的相关概念理解不深刻导致的,同时充分说明了,要抠细节,一定要对各个语法概念有一个明确、清晰的认识。