JavaScript物件導向精要(二)

來源:互聯網
上載者:User

標籤:javascript

建構函式和原型對象

建構函式也是函數,用new建立對象時調用的函數,與普通函數的一個區別是,其首字母應該大寫。但如果將建構函式當作普通函數調用(缺少new關鍵字),則應該注意this指向的問題。

var name = "Pomy";function Per(){    console.log("Hello "+this.name);}var per1 = new Per();  //"Hello undefined"var per2 = Per();   //"Hello Pomy"

使用new時,會自動建立this對象,其類型為建構函式類型,指向對象執行個體;缺少new關鍵字,this指向全域對象。
可以用instanceof來檢測物件類型,同時每個對象在建立時都自動擁有一個constructor屬性,指向其建構函式(字面量形式或Object建構函式建立的對象,指向Object,自訂建構函式建立的對象則指向它的建構函式)。

console.log(per1 instanceof Per);  //trueconsole.log(per1.constructor === Per); //true

每個對象執行個體都有一個內部屬性:[[Prototype]],其指向該對象的原型對象。建構函式本身也具有prototype屬性指向原型對象。所有建立的對象都共用該原型對象的屬性和方法。

function Person(){}Person.prototype.name="dwqs";Person.prototype.age=20;Person.prototype.sayName=function(){    alert(this.name);};var per1 = new Person();per1.sayName();  //dwqsvar per2 = new Person();per2.sayName();  //dwqsalert(per1.sayName == per2.sayName);  //true


所以,**執行個體中的指標僅指向原型,而不指向建構函式。**ES5提供了hasOwnProperty()和isPropertyOf()方法來反應原型對象和執行個體之間的關係

alert(Person.prototype.isPrototypeOf(per2));  //trueper1.blog = "www.ido321.com";alert(per1.hasOwnProperty("blog"));  //truealert(Person.prototype.hasOwnProperty("blog"));  //falsealert(per1.hasOwnProperty("name"));  //falsealert(Person.prototype.hasOwnProperty("name"));  //true

因為原型對象的constructor屬性是指向建構函式本身,所以在重寫原型時,需要注意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);  //trueconsole.log(hi.constructor === Hello); //falseconsole.log(hi.constructor === Object); //true

使用對象字面量形式改寫原型對象改變了建構函式的屬性,因此constructor指向Object,而不是Hello。如果constructor指向很重要,則需要在改寫原型對象時手動重設其constructor屬性

Hello.prototype = {    constructor:Hello,    sayHi:function(){        console.log(this.name);    }};console.log(hi.constructor === Hello); //trueconsole.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);  //21String.prototype.capit = function(){    return this.charAt(0).toUpperCase()+this.substring(1);};var msg = "hello world";console.log(msg.capit()); //"Hello World"
繼承

利用[[Prototype]]特性,可以實現原型繼承;對於字面量形式的對象,會隱式指定Object.prototype為其[[Prototype]],也可以通過Object.create()顯示指定,其接受兩個參數:第一個是[[Prototype]]指向的對象(原型對象),第二個是可選的屬性描述符對象。

var book = {    title:"這是書名";};//和下面的方式一樣var book = Object.create(Object.prototype,{    title:{        configurable:true,        enumerable:true,        value:"這是書名",        wratable:true    }});

字面量對象會預設繼承自Object,更有趣的用法是,在自訂對象之間實現繼承。

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"));  //trueconsole.log(book1.isPropertyOf("book2"));  //trueconsole.log(book2.hasOwnProperty("getTitle"));  //false

當訪問book2的getTitle屬性時,JavaScript引擎會執行一個搜尋過程:現在book2的自有屬性中尋找,找到則使用,若沒有找到,則搜尋[[Prototype]],若沒有找到,則繼續搜尋原型對象的[[Prototype]],直到繼承鏈末端。末端通常是Object.prototype,其[[Prototype]]被設定為null。

實現繼承的另外一種方式是利用建構函式。每個函數都具有可寫的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());  //50console.log(square.getArea());  //36

如果要訪問父類的toString(),可以這樣做:

Square.prototype.toString = function(){    var text = Rect.prototype.toString.call(this);    return text.replace("Rect","Square");}

相關文章:
DOM筆記(十二):又談原型對象
DOM筆記(十三):JavaScript的繼承方式

原文:http://www.ido321.com/1586.html

JavaScript物件導向精要(二)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.