js在es6之前的繼承是五花八門的。而且要在專案中靈活運用物件導向寫法也是有點彆扭,更多的時候還是覺得面向過程的寫法更為簡單,效率也高。久而久之對js的繼承每隔一段時間就會理解出現困難。所以這次我要把對物件的理解寫下來,這樣應該就深刻一點了。我們先來看看乙個物件是怎麼生成的
// 三種建立物件的方法
var obj = {}
var obj2 = new object()
var obj3 = object.create(null)
// 建立乙個空字串物件
var obj4 = new string()
obj.constructor === obj2.constructor // true
obj.__proto__ === obj2.__proto__ === object.prototype // true
obj4.__proto__ === string.prototype // true
obj4.__proto__.__proto__ === object.prototype // ture
這三種方法,前面兩種是一樣的。它們建立的空物件都具有原型,而第三種方式建立的是乙個真正意義上的空物件,它不繼承任何屬性;而obj4呢是乙個字串物件。看下圖的對比:這裡obj和obj2雖然是空物件,不過它們具有object建構函式的屬性的方法,而obj4除了有obj擁有的屬性和方法,它還具備了string擁有的屬性和方法;而obj3是真正的空物件,它的__proto__指向的是null。下面物件除了obj3都有個__proto__的隱性屬性,這個屬性指向的是該建立該例項的建構函式的原型。
我們再將obj4全部展開看看:
再來看看它們之間的關係:
如上圖,我舉得例子是object和string這兩個原生具有的構造器。它們的關係和我們平時寫的父類和子類之間的關係是一樣的,所有的類最終都會指向object。在es5的時代,我們用到的繼承最簡單的就是原型鏈繼承了
// 我們先建立乙個父類
function super (name)
super.prototype.move = function ()
// 子類繼承父類
function child (name)
child.prototype = new super()
// 原型鏈繼承,子類原型的私有方法和屬性要在繼承之後新增,不然會被覆蓋
child.prototype.constructor = child // 修復對建構函式的指向
child.prototype.eat = function ()
原型鏈繼承就是將子類的原型等於父類的例項,然後再新增子類原型的屬性和方法。這樣的缺點就是只能繼承乙個父類。而且在建立子類的例項的時候,不能傳參給父類。在做單一繼承而且父類不需要傳參的時候,這種寫法是最好的選擇了。下面在介紹一種我個人覺得已經很不錯的繼承方式(組合繼承)
// 子類繼承父類
function child (name)
child.prototype = new super()
child.prototype.constructor = child // 修復對建構函式的指向
child.prototype.eat = function ()
一般來說這種繼承方式已經很好了,**量少。繼承性好,弊端也沒有影響。這就是es6之前的繼承。下面再來看看es6是怎麼操作的。
上面這兩句話是引用阮一峰對es6的class的簡介(class 的基本語法)。阮大神的ecmascript 6 入門真的是對es6初學者居家必備的好東西。我在這裡就談談我的理解好了。
// 寫乙個class
class point
tostring()
}var point = new point(2, 3) // new乙個例項
下面看下point內部是怎樣的,可以看出constructor,tostring都是在「proto」內的。
在這裡會等價於建構函式的什麼寫法呢
// 寫乙個class
function point (x, y)
point.prototype.tostring = function ()
var point = new point(2, 3) // new乙個例項
在不考慮class靜態屬性的情況下,可以簡單理解為constructor內this下的新屬性和方法都屬於建構函式內的,而constructor外的方法都是prototype下的。
class childpoint extends point
tostring ()
changex (x)
}var childpoint = new childpoint(2, 3, 4) // new乙個childpoint的例項
console.log(childpoint.x) // 2
console.log(childpoint.y) // 3
console.log(childpoint.z) // 4
console.log(childpoint.tostring()) // 2,3,4
childpoint.changex(5)
console.log(childpoint.x) // 5
console.log(childpoint.__proto__ === childpoint.prototype) // true
console.log(childpoint.__proto__.__proto__ === point.prototype) // true
console.log(childpoint.constructor === childpoint) // true
這裡class是通過extends繼承父類的,而子類的constructor方法內需要呼叫super()方法,這相當與呼叫了父類的constructor()方法。
下面看下childpoint的內部情況:
從和上面列印的情況可以看出,es6的繼承和組合繼承很是相似。唯一的不同點就是es6的繼承沒有組合繼承產生的多餘的乙份例項屬性在原型裡。看起來很順眼。不過相對的es6的不能多繼承(雖然組合繼承只能多繼承多個建構函式,並不能繼承多個原型)。
其實組合繼承還可以進一步公升級成es6繼承那個樣子的(寄生組合繼承):
// 我們先建立乙個父類
function super (name)
super.prototype.move = function ()
// 子類繼承父類
function child (name)
(function()
middlesuper.prototype = super.prototyoe // 跟super共享原型
// 在這裡middlesuper和super的區別就是有沒有例項了。
// 然後在正常進行組合繼承的操作
child.prototype = new middlesuper()
})()
child.prototype.constructor = child // 修復對建構函式的指向
child.prototype.eat = function ()
經過這一系列複雜的操作後我們就得到了乙份和es6一樣的結構了。不過es6只需要乙個extends,而es6之前我們就得長篇大論的寫才能實現,而且還特別繞。所以一句話,快去學es6吧。
更多專業前端知識,請上
【猿2048】www.mk2048.com
JS繼承的一些見解
js在es6之前的繼承是五花八門的。而且要在專案中靈活運用物件導向寫法也是有點彆扭,更多的時候還是覺得面向過程的寫法更為簡單,效率也高。久而久之對js的繼承每隔一段時間就會理解出現困難。所以這次我要把對物件的理解寫下來,這樣應該就深刻一點了。我們先來看看乙個物件是怎麼生成的 三種建立物件的方法 va...
個人對JS的一些見解
優點 1.廣泛,無論對於使用者還是開發者,可以說是最廣泛使用的程式語言 2.生態完美,多個端 多類庫 多種框架,眾多優秀團隊支援,迄今沒有任何一種語言能做到,真正的眾星拱月 3.能處理任何形式資料,特別是對於json的處理 4.易用,對初學相當友好,你只需要裝乙個瀏覽器,就能進行開發 5.特別適合於...
CSRF XSS Cookies 的一些見解
csrf 攻擊 在瀏覽器中插入了 惡意鏈結 並在使用者訪問之時讓使用者訪問,達到使用使用者的cooikes達到連線指定伺服器客戶的的驗證資訊,並進行一些簡單的操作。比如 防禦 最簡單的,可以通過驗證cookies進行一些防禦。例如在使用者操作驗證中,判斷是否又cookies傳過來,如果沒有則是惡意鏈...