1、什麼是原型(prototype)數組
一、prototype本質上仍是一個JavaScript對象;函數
二、每一個函數都有一個默認的prototype屬性;this
三、經過prototype咱們能夠擴展Javascript的內建對象spa
若是這個函數被用在建立自定義對象的場景中,咱們稱這個函數爲構造函數。 好比:prototype
代碼
//
構造函數
function
Person(name) {
this
.name
=
name;
}
//
定義Person的原型,原型中的屬性能夠被自定義對象引用
Person.prototype
=
{getName:
function
() {
return
this
.name;
}};
var
zhang
=
new
Person(
"
ZhangSan
"
);
console.log(zhang.getName());
//
"ZhangSan"
咱們能夠經過prototype擴展Javascript的內建對象,例如:code
代碼
//
向JavaScript固有類型Array擴展一個獲取最小值的方法
Array.prototype.min
=
function
() {
var
min
=
this
[
0
];
for
(
var
i
=
1
; i
<
this
.length; i
++
) {
if
(
this
[i]
<
min) {
min
=
this
[i];
}
}
return
min;
};
//
在任意Array的實例上調用min方法
console.log([
1
,
56
,
34
,
12
].min());
//
1
注意:這裏有一個陷阱,向Array的原型中添加擴展方法後,當使用for-in循環數組時,這個擴展方法也會被循環出來。對象
下面的代碼說明這一點(假設已經向Array的原型中擴展了min方法):blog
var
arr
=
[
1
,
56
,
34
,
12
];
var
total
=
0
;
for
(
var
i
in
arr) {
total
+=
parseInt(arr[i],
10
);
}
console.log(total);
//
NaN
解決方法也很簡單:ip
var
arr
=
[
1
,
56
,
34
,
12
];
var
total
=
0
;
for
(
var
i
in
arr) {
if
(arr.hasOwnProperty(i)) {
total
+=
parseInt(arr[i],
10
);
}
}
console.log(total);
//
103
2、構造器(constructor)get
一、constructor始終指向建立當前對象的構造(初始化)函數。
二、每一個函數都有一個默認的屬性prototype,而這個prototype的constructor默認指向這個函數
咱們來看個例子:
代碼
//
等價於 var arr = new Array(1, 56, 34, 12);
var
arr
=
[
1
,
56
,
34
,
12
];
console.log(arr.constructor
===
Array);
//
true
//
等價於 var foo = new Function();
var
Foo
=
function
() {
};
console.log(Foo.constructor
===
Function);
//
true
//
由構造函數實例化一個obj對象
var
obj
=
new
Foo();
console.log(obj.constructor
===
Foo);
//
true
//
將上面兩段代碼合起來,就獲得下面的結論
console.log(obj.constructor.constructor
===
Function);
//
true
可是當constructor遇到prototype時,有趣的事情就發生了。
咱們知道每一個函數都有一個默認的屬性prototype,而這個prototype的constructor默認指向這個函數。以下例所示:
代碼
function
Person(name) {
this
.name
=
name;
}
Person.prototype.getName
=
function
() {
return
this
.name;
};
var
p
=
new
Person(
"
ZhangSan
"
);
console.log(p.constructor
===
Person);
//
true
console.log(Person.prototype.constructor
===
Person);
//
true
//
將上兩行代碼合併就獲得以下結果
console.log(p.constructor.prototype.constructor
===
Person);
//
true
當時當咱們從新定義函數的prototype時(注意:和上例的區別,這裏不是修改而是覆蓋), constructor的行爲就有點奇怪了,以下示例
代碼
function
Person(name) {
this
.name
=
name;
}
Person.prototype
=
{getName:
function
() {
return
this
.name;
}};
var
p
=
new
Person(
"
ZhangSan
"
);
console.log(p.constructor
===
Person);
//
false
console.log(Person.prototype.constructor
===
Person);
//
false
console.log(p.constructor.prototype.constructor
===
Person);
//
false
爲何呢?
原來是由於覆蓋Person.prototype時,等價於進行以下代碼操做:
Person.prototype
=
new
Object({getName:
function
() {
return
this
.name;
}});
而constructor始終指向建立自身的構造函數,因此此時Person.prototype.constructor === Object
怎麼修正這種問題呢?方法也很簡單,從新覆蓋Person.prototype.constructor便可:
代碼
function
Person(name) {
this
.name
=
name;
}
Person.prototype
=
new
Object({getName:
function
() {
return
this
.name;
}});
Person.prototype.constructor
=
Person;
var
p
=
new
Person(
"
ZhangSan
"
);
console.log(p.constructor
===
Person);
//
true
console.log(Person.prototype.constructor
===
Person);
//
true
console.log(p.constructor.prototype.constructor
===
Person);
//
true