版權聲明:本文為部落客原創文章,轉載請注明出處。 https://blog.csdn.net/twilight_karl/article/details/59700099
prototype
聽說prototype是JavaScript中最難的部分,最近學習了相關知識,感覺确實挺複雜,主要是比較難了解。為了避免遺忘,将最近的學習做一個簡單的總結。
prototype類似java中的靜态方法和靜态變量。可以實作共享。對象中的proto指針指向prototype,prototype儲存着該類的“靜态屬性和方法和constructor”。constructor 可以擷取構造函數本身。
構造函數中的方法分為執行個體方法和原型方法,構造函數中定義的方法是執行個體方法。prototype指向的方法是原型方法。
//定義原型方法和原型屬性
function Person(){}
Person.prototype.height = 180;
Person.prototype.sex = "man";
Person.prototype.fun = function (){
return this.height+this.sex;
};
直接輸出constructor會輸出構造函數的函數體。
alert(tom.__proto__.constructor);
使用時的執行流程: 現在執行個體對象中找,如果找不到再到原型對象中找。(通路–>執行個體對象–>原型對象)
删除原型屬性:
delete Person.prototype.name;
isPrototypeOf()
判斷一個屬性是否指向自己的原型
Box.prototype.isPrototypeOf(屬性);
var tom = new Person();
var jerry = new Person();
var obj = new Object();
var flag = Person.prototype.isPrototypeOf(tom); // true
var flag = Person.prototype.isPrototypeOf(obj); // true
var flag = Object.prototype.isPrototypeOf(tom); // false
是以,所有對象都指向Object的原型。如果改變object對象指向的原型,就改變了所有對象的原型。但是原型是單向的,所有對象都指向Object,但是Object不會指向其他對象
Object.prototype.name = "zhangsan";
hasOwnProperty(屬性名) // ???
判斷是否存在指定的執行個體屬性。
in
查找執行個體和原型中的屬性,隻要存在就傳回
屬性名 in 對象名
隻判斷原型中的屬性(自定義函數)
hasOwnProperty傳回false && in傳回true 時滿足要求
封裝
對象的屬性分為執行個體屬性和原型屬性,為了将類封裝成一個整體,可以把原型屬性寫在構造函數内,但是這種方式每次建立對象時都會建立原型屬性,比較浪費資源:
function Fun(name , age){
this.name = name ;
this.age = age;
Fun.prototype.run = function (){
return this.name+this.age+"#";
};
}
可以采取這種優化的方法,判斷原型對象是否被建立過,隻在第一次使用時建立原型屬性:
function Fun2(name , age){
this.name = name ;
this.age = age;
if(typeof Fun2.prototype.run != 'function'){ alert("#");
Fun2.prototype.run = function(){
return this.name + this.age+"#";
}
}
}
繼承
原型鍊繼承
被繼承叫做超類型,繼承的函數叫做子類型,繼承的對象可以使用父類的執行個體和原型屬性。
所有對象都是繼承自Object對象
// 繼承
function A(){
this.name = "a";
this.age = 20;
}
A.prototype.name = "prototype_a"; // 原型屬性
function B(){
this.name = "b";
}
B.prototype = new A(); // 使 B 繼承 A
var obj = new B();
alert(obj.age); // 20
alert(obj.name); // b 本地屬性覆寫父類屬性
對象冒充
對象冒充無法繼承父類的prototype屬性,隻能冒充構造函數中的資訊。冒充的對象類型不變
function C(name){
this.name = name;
this.age = 100;
this.sss = new Array(1,2,3,4,5);
}
C.prototype.family = "family";
function D(name ,age ){
C.call(this,name);
}
var d = new D("zhangsan",20);
alert(d.name); //zhangsan
alert(d.age); //100
alert(d.family); //1,2,3,4,5
alert(d instanceof D); //true
組合模式
在冒充的基礎上使用繼承,這樣就可以繼承原型方法
function E(name){
this.name = name;
this.sss = [1,2,3,4,5];
}
E.prototype.family = "prototype_family";
function F(name , age){
E.apply(this,[name]);
}
F.prototype = new E();
var f = new F("lisi",40);
alert(f.family); // 1,2,3,4,5
原型式繼承
對象時采用引用的關系。
// 原型式繼承
function G(obj){
var Temp = function (){}
Temp.prototype = obj;
return new Temp();
}
var data = {
name:"zhangsanG",
age:20,
family:[1,2,3,4,5]
};
var g = new G(data);
g.family.push(6);
alert(data.family); //1,2,3,4,5,6
var gg = new G(data);
alert(gg.family); // 1,2,3,4,5,6