本文通過例項給大家介紹js原型鏈存在的問題解析,非常不錯,具有參考借鑑價值,感興趣的朋友一起看看吧
我們知道使用原型鏈實現繼承是乙個goodway:)看個原型鏈繼承的例子。
?
1
2
3
4
5
6
7
8
9
10
11
function
a ()
a.prototype.getabc =
function
();
function
b()
b.prototype =
new
a();
// b通過a的例項完成了繼承,形成了原型鏈(b的原型就是a的例項)
var
b =
new
b();
b.getabc();
關係如下:b(例項) ->b.prototype = new a() -> a.prototype ->object.prototype
可是在這種看似「漂亮」的繼承方法中確存在問題。
1. 最主要的問題來自包含引用型別值的原型,我們知道共享原型是存在問題的,丟擲乙個例子
?
1
2
3
4
5
6
7
8
9
10
function
person ()
person.prototype =
var
person1 =
new
person();
var
person2 =
new
person();
person1.friends.push(
"c"
);
console.log(person1.friends);
// "a","b","c"
console.log(person2.friends);
//"a","b","c"
通過引用例項改變了原型中本來中的值,同時也影響了其他例項。(這就是為什麼引用型別值要定義在建構函式中而非原型中的原因)
在原型鏈中同樣也會有同樣的情況出現:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
function
a ()
function
b()
b.prototype =
new
a();
var
b =
new
b();
var
a =
new
a();
b.numbers.push(4);
b.numbers;
//1234
var
b2 =
new
b();
b2.numbers;
//1234
a.numbers;
//123
我們看到出現了和上面一樣的情況(在通過原型來繼承時,原型實際上會變成另乙個型別的例項。於是原先的例項屬性也就順理成章的變成了現在原型屬性了)。
可是我們看到a的例項a.numbers;依然是123,說明在b繼承a的例項時是複製了a例項中的所有屬性(包括prototype指標,形成原型鏈)並非引用(其實這裡有疑問,是因為繼承的是a()的例項所以才不會影響a()建立其他例項的表現嗎?)。
2.在建立子類例項時,不可以在不影響所有物件例項的情況下給超類傳遞引數。
?
1
2
3
4
5
6
7
8
9
10
11
function
a (light) ;
function
b (light) ;
//給b賦值的同時,想給a賦值,無法實現
b.prototype =
new
a();
var
c =
new
b(123);
console.log(c.light);
console.log(c.light1);
想實現這個需要手動呼叫a的建構函式,會影響其他例項
?
1
2
3
4
5
6
7
8
9
10
11
12
function
a (light) ;
function
b (light) ;
//給b賦值的同時,給a賦值
b.prototype =
new
a();
var
c =
new
b(123);
console.log(c.light);
console.log(c.light1);
JavaScript中原型和原型鏈
原型 prototype 為其他物件提供共享屬性的物件。每個函式都有乙個原型 prototype 屬性,這個屬性是乙個指標,指向乙個物件,這個物件包含特定例項共享的一些屬性和方法。以例服人 這個例子說明了原型物件是共享的,並且是乙個指標,並且物件的例項中也有指向prototype指向物件的指標。fu...
JavaScript中原型鏈的那些事
在物件導向的語言中繼承是非常重要的概念,許多物件導向語言都支援兩種繼承方式 介面繼承和實現繼承。介面繼承制只繼承方法簽名,而實現繼承繼承實際的方法。在ecmascript中函式沒有簽名,所以ecmascript無法實現介面繼承,只能實現實現繼承。那麼是怎麼實現實現繼承的呢?這就要說一說js中的原型鏈...
js中原型和原型鏈
let hd new object object.prototype.show function function getname console.dir getname console.log getname.prototype.proto getname.proto proto true con...