理解javascript的constructor

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
/* oloo 对象链接其他对象*/
var Animal={
val:[1,2,3,4],
setVal:function(val){
this.val=val;
return
}
};
var Mankey=Object.create(a);
Mankey.val[0]=3;
/*原型继承*/
function Person(name){
this.name=name;
}
Person.prototype={
getName:function(){
return this.name;
}
};
function Man(){
Person.apply(this,arguments);
}
Man.prototype=new Person();
var man1=new Man('tom');
function Woman(){
Person.apply(this,arguments);
}
Woman.prototype=Object.create(Person.prototype);
var woman1=new Woman('july');

再看个栗子

1
2
Function instanceof Object ;//true
Object instanceof Function; //true

为啥呢
instanceof 运算符

instanceof是一个二元运算符,如:A instanceof B. 其中,A必须是一个合法的JavaScript对象,B必须是一个合法的JavaScript函数 (function). 判断过程如下:
如果函数B在对象A的原型链 (prototype chain) 中被发现,那么instanceof操作符将返回true,否则返回false.
例如下面的代码会返回true.

1
2
3
4
5
6
Function.__proto__.__proto__;//Object {}
Object.__proto__;//function () {}
Object/Function/Array 都是原生对象,也是构造函数,所以
Object instanceof Functiontrue
Function.prototype又是一个对象,所以他的构造函数是Object,所以
Function instanceof Objecttrue

所以以下就很容易理解了

1
2
Function instanceof Function;//true
Object instanceof Object;//true

img

如下,虽然constructor可以用来检查某个实例的构造函数,但是,我们经常会重写prototype,导致constructor属性会重写

1
2
3
4
5
6
7
8
9
10
11
12
function Book() {
}
Book.prototype={
getName:function(){}
};
var myBook = new Book();
//false
console.log(myBook.constructor===Book);
//true Book在myBook的原型链上
console.log(myBook.__proto__===Book.prototype);
//true
console.log(myBook instance of Book);

Object.defineProperty函数

该函数可用于constructor中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Book(name) {
Object.defineProperty(this, "name", {
get: function() {
return "Book: " + name;
},
set: function(newName) {
name = newName;
},
configurable: false
});
}
var myBook = new Book("Single Page Web Applications");
console.log(myBook.name); // Book: Single Page Web Applications
// we cannot delete the name property because "configurable" is set to false
delete myBook.name;
console.log(myBook.name); // Book: Single Page Web Applications
// but we can change the value of the name property
myBook.name = "Testable JavaScript";
console.log(myBook.name); // Book: Testable JavaScript

对象字面量优于构造函数创建

js有个9个內建对象(构造函数),Object、Array、String、Number、Boolean、Date、Function、Error、RegExp
创建这几个对象的实例可以通过对象字面量或者构造函数创建。但是对象字面量的可读性强、而且他们性能更好,因为他们在编译阶段会被优化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// a number object
// numbers have a toFixed() method
var obj = new Object(5);
obj.toFixed(2); // 5.00
// we can achieve the same result using literals
var num = 5;
num.toFixed(2); // 5.00
// a string object
// strings have a slice() method
var obj = new String("text");
obj.slice(0,2); // "te"
// same as above
var string = "text";
string.slice(0,2); // "te"

构造函数方式可能引发的诡异bug

1
2
3
4
5
function Object() {
// Oh crap, we have redefined Object!
return []; // return an array because we are EVIL
}
var person = new Object(); // not what we think it is

更多分析:
Javascript object constructor vs object literal [duplicate]

使用new创建实例

作用域安全的构造函数

1
2
3
4
5
6
7
function Book(name, year) {
if (!(this instanceof Book)) {
return new Book(name, year);
}
this.name = name;
this.year = year;
}

总结

js没有类,这对经常使用其它语言的人比较有障碍,但是js有constructor来实现相同的功能,constructor和普通函数一样,只是使用时多了个new。使用类让我们可以方便的实现多个具有相同属性和方法的对象。