摘要:使用時,會自動創建對象,其類型為構造函數類型,指向對象實例缺少關鍵字,指向全局對象。構造函數本身也具有屬性指向原型對象。
在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); //true console.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(); //dwqs var per2 = new Person(); per2.sayName(); //dwqs alert(per1.sayName == per2.sayName); //true
所以,實例中的指針僅指向原型,而不指向構造函數。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屬性是指向構造函數本身,所以在重寫原型時,需要注意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
使用對象字面量形式改寫原型對象改變了構造函數的屬性,因此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]]特性,可以實現原型繼承;對于字面量形式的對象,會隱式指定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")); //true console.log(book1.isPrototypeOf("book2")); //false console.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()); //50 console.log(square.getArea()); //36
如果要訪問父類的toString(),可以這樣做:
Square.prototype.toString = function(){ var text = Rect.prototype.toString.call(this); return text.replace("Rect","Square"); }原文:http://www.ido321.com/1586.html
相關文章:
DOM筆記(十二):又談原型對象
DOM筆記(十三):JavaScript的繼承方式
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85727.html
摘要:面向對象精要讀書筆記下面代碼的實際執行過程是什么使用原始值和原始封裝類型是有區別的因為是被解析成一個對象的,所以肯定是真的函數是對象,函數有兩種字面形式,第一種是函數聲明,以關鍵字開頭后面跟函數名字。 Javascript面向對象精要讀書筆記 1、下面代碼的實際執行過程是什么? var name = fan var str = name.charAt(0) console.l...
摘要:使函數不同于其他對象的決定性特性是函數存在一個被稱為的內部屬性。其中,是一個布爾值,指明改對象本身是否可以被修改值為。注意凍結對象和封印對象均要在嚴格模式下使用。 數據類型 在JavaScript中,數據類型分為兩類: 原始類型:保存一些簡單數據,如true,5等。JavaScript共有5中原始類型: boolean:布爾,值為true或false number:數字,值...
摘要:解除引用的最佳手段是將對象變量設置為。字面形式允許你在不需要使用操作符和構造函數顯示創建對象的情況下生成引用值。函數就是值可以像使用對象一樣使用函數因為函數本來就是對象,構造函數更加容易說明。 JavaScript(ES5)的面向對象精要 標簽: JavaScript 面向對象 讀書筆記 2016年1月16日-17日兩天看完了《JavaScript面向對象精要》(參加異步社區的活動送...
摘要:與使用作為接口的唯一標識類似,使用稱之為的一個字節無符號整數作為唯一標識。接口是客戶程序和組件程序之間的橋梁,接口應該具有不變性,并且一個對象也應該支持多個接口。 COM是Component Object Model (組件對象模型)的縮寫。BREW基本上遵從COM這一組件構架的。組...
閱讀 2187·2021-11-18 10:02
閱讀 3289·2021-11-11 16:55
閱讀 2694·2021-09-14 18:02
閱讀 2426·2021-09-04 16:41
閱讀 2056·2021-09-04 16:40
閱讀 1165·2019-08-30 15:56
閱讀 2213·2019-08-30 15:54
閱讀 3161·2019-08-30 14:15