JavaScript面向對象精要(下部)
構造函數(shù)和原型對象
構造函數(shù)也是函數(shù),用new創(chuàng)建對象時調用的函數(shù),與普通函數(shù)的一個區(qū)別是,其首字母應該大寫。但如果將構造函數(shù)當作普通函數(shù)調用(缺少new關鍵字),則應該注意this指向的問題。
var name = "Pomy";
function Per(){
console.log("Hello "+this.name);
}
var per1 = new Per(); //"Hello undefined"
var per2 = Per(); //"Hello Pomy"
使用new時,會自動創(chuàng)建this對象,其類型為構造函數(shù)類型,指向對象實例;缺少new關鍵字,this指向全局對象。
可以用instanceof來檢測對象類型,同時每個對象在創(chuàng)建時都自動擁有一個constructor屬性,指向其構造函數(shù)(字面量形式或Object構造函數(shù)創(chuàng)建的對象,指向Object,自定義構造函數(shù)創(chuàng)建的對象則指向它的構造函數(shù))。
console.log(per1 instanceof Per); //true console.log(per1.constructor === Per); //true
每個對象實例都有一個內部屬性:[[Prototype]],其指向該對象的原型對象。構造函數(shù)本身也具有prototype 屬性指向原型對象。所有創(chuàng)建的對象都共享該原型對象的屬性和方法。
function Person(){}
Person.prototype.name="dwqs";
Person.prototype.age=20;
Person.prototype.sayName=function()
{
alert(this.name);
};
var per1 = new Person();
per1.sayName(); //dwqs
var per2 = new Person();
per2.sayName(); //dwqs
alert(per1.sayName == per2.sayName); //true

所以,實例中的指針僅指向原型,而不指向構造函數(shù)。 ES5提供了hasOwnProperty()和isPropertyOf()方法來反應原型對象和實例之間的關系
alert(Person.prototype.isPrototypeOf(per2)); //true
per1.blog = "www.ido321.com";
alert(per1.hasOwnProperty("blog")); //true
alert(Person.prototype.hasOwnProperty("blog")); //false
alert(per1.hasOwnProperty("name")); //false
alert(Person.prototype.hasOwnProperty("name")); //true
因為原型對象的constructor屬性是指向構造函數(shù)本身,所以在重寫原型時,需要注意constructor屬性的指向問題。
function Hello(name){
this.name = name;
}
//重寫原型
Hello.prototype = {
sayHi:function(){
console.log(this.name);
}
};
var hi = new Hello("Pomy");
console.log(hi instanceof Hello); //true
console.log(hi.constructor === Hello); //false
console.log(hi.constructor === Object); //true
使用對象字面量形式改寫原型對象改變了構造函數(shù)的屬性,因此constructor指向Object,而不是Hello。如果constructor指向很重要,則需要在改寫原型對象時手動重置其constructor屬性
Hello.prototype = {
constructor:Hello,
sayHi:function(){
console.log(this.name);
}
};
console.log(hi.constructor === Hello); //true
console.log(hi.constructor === Object); //false
利用原型對象的特性,我們可以很方便的在JavaScript的內建原型對象上添加自定義方法:
Array.prototype.sum=function(){
return this.reduce(function(prev,cur){
return prev+cur;
});
};
var num = [1,2,3,4,5,6];
var res = num.sum();
console.log(res); //21
String.prototype.capit = function(){
return this.charAt(0).toUpperCase()+this.substring(1);
};
var msg = "hello world";
console.log(msg.capit()); //"Hello World"
繼承
利用[[Prototype]]特性,可以實現(xiàn)原型繼承;對于字面量形式的對象,會隱式指定Object.prototype為其[[Prototype]],也可以通過Object.create()顯示指定,其接受兩個參數(shù):第一個是[[Prototype]]指向的對象(原型對象),第二個是可選的屬性描述符對象。
var book = {
title:"這是書名";
};
//和下面的方式一樣
var book = Object.create(Object.prototype,{
title:{
configurable:true,
enumerable:true,
value:"這是書名",
wratable:true
}
});
字面量對象會默認繼承自Object,更有趣的用法是,在自定義對象之間實現(xiàn)繼承。
var book1 = {
title:"JS高級程序設計",
getTitle:function(){
console.log(this.title);
}
};
var book2 = Object.create(book1,{
title:{
configurable:true,
enumerable:true,
value:"JS權威指南",
wratable:true
}
});
book1.getTitle(); //"JS高級程序設計"
book2.getTitle(); //"JS權威指南"
console.log(book1.hasOwnProperty("getTitle")); //true
console.log(book1.isPrototypeOf("book2")); //false
console.log(book2.hasOwnProperty("getTitle")); //false
當訪問book2的getTitle屬性時,JavaScript引擎會執(zhí)行一個搜索過程:現(xiàn)在book2的自有屬性中尋找,找到則使用,若沒有找到,則搜索[[Prototype]],若沒有找到,則繼續(xù)搜索原型對象的[[Prototype]],直到繼承鏈末端。末端通常是Object.prototype,其[[Prototype]]被設置為null。
實現(xiàn)繼承的另外一種方式是利用構造函數(shù)。每個函數(shù)都具有可寫的prototype屬性,默認被自懂設置為繼承自Object.prototype,可以通過改寫它來改變原型鏈。
function Rect(length,width){
this.length = length;
this.width = width;
}
Rect.prototype.getArea = function(){
return this.width * this.length;
};
Rect.prototype.toString = function(){
return "[Rect"+this.length+"*"+this.width+"]";
};
function Square(size){
this.length = size;
this.width = size;
}
//修改prototype屬性
Square.prototype = new Rect();
Square.prototype.constructor = Square;
Square.prototype.toString = function(){
return "[Square"+this.length+"*"+this.width+"]";
};
var rect = new Rect(5,10);
var square = new Square(6);
console.log(rect.getArea()); //50
console.log(square.getArea()); //36
如果要訪問父類的toString(),可以這樣做:
Square.prototype.toString = function(){
var text = Rect.prototype.toString.call(this);
return text.replace("Rect","Square");
}
相關文章
JS+ACTIVEX實現(xiàn)網(wǎng)頁選擇本地目錄路徑對話框
使用ACTIVEX對象遍歷本地磁盤和目錄,只需網(wǎng)頁啟用相關ACTIVEX的INTERNET選項即可實現(xiàn)路徑選擇對話框,感興趣的你可以參考下哈希望可以幫助到你2013-03-03
微信小程序實現(xiàn)簡單input正則表達式驗證功能示例
這篇文章主要介紹了微信小程序實現(xiàn)簡單input正則表達式驗證功能,結合實例形式分析了微信小程序input組件事件綁定及正則驗證相關操作技巧,需要的朋友可以參考下2017-11-11

