大多數程式語言中,都有類別和對象,一個類別可以繼承其他類別。
在JavaScript中,繼承是基於原型的(prototype-based),這意味著JavaScript中沒有類,取而代之的是一個物件繼承另一個物件。 :)
1. 繼承, the proto
在JavaScript中,當一個物件rabbit繼承另一了物件animal時,這表示rabbit物件中將會有一個特殊的屬性:rabbit.__proto__ = animal;
當存取rabbit物件時,如果解釋器在rabbit中無法找到屬性,那麼它會順著__proto__鏈往上在animal物件中尋找
栗子中的__proto__屬性僅在Chrome和FireFox中可以訪問,請看一個栗子:
var animal = { eats: true } var rabbit = { jumps: true } rabbit.__proto__ = animal // inherit alert(rabbit.eats) // true
eats屬性是從animal物件中存取的。
如果在rabbit物件中已經發現了屬性,那就不會去檢查proto屬性啦。
再來一個栗子,當子類別中也有eats屬性時,父類別中的就不會被存取了。
var animal = { eats: true } var fedUpRabbit = { eats: false} fedUpRabbit.__proto__ = animal alert(fedUpRabbit.eats) // false
你也可以在animal中加入一個函數,那麼在rabbit中也可以存取了。
var animal = { eat: function() { alert( "I'm full" ) this.full = true } } var rabbit = { jump: function() { /* something */ } } rabbit.__proto__ = animal
(1)rabbit.eat():
rabbit.eat()函數如下兩步驟執行:
首先,解譯器尋找rabbit.eat,rabbit中沒有eat函數,那麼它就順著rabbit.__proto__往上找,在animal中找到了。
函數以this = rabbit運行。 this值與__proto__屬性完全無關。
因此,this.full = true在rabbit中:
看看這裡我們有什麼新發現,一個物件呼叫了父類別函數,但是this還是指向物件本身,這就是繼承。
被__proto__引用的物件稱為原型(prototype),animal是rabbit的原型(譯者註:這就是rabbit的__proto__屬性引用了animal 的prototype屬性)
(2)讀時查找,不是寫時
當讀取一個物件時,例如this.prop,解釋器會在它的原型中尋找屬性。
當設定一個屬性值時,例如this.prop = value,那就沒有理由去查找了,這個屬性(prop)會被直接加入到這個物件中(這裡是this)。 delete obj.prop也類似,它只刪除物件本身的屬性,原型中的屬性保持原封不動。
(3)關於proto
如果你在閱讀指南,這裡我們叫的__proto__,在指南中表示為[[Prototype]]。雙方括號是很重要的,因為有另一個屬性叫做prototype。
2. Object.create, Object.getPrototypeOf
__proto__是一個非標準的屬性,由Chrome/FireFox提供訪問,在其他的瀏覽器中保持不可見。
所有的現代瀏覽器除了Opera(IE > 9)支援兩個標準的函數來處理原型問題:
Object.ceate(prop[,props])
用給定了proto建立一個空物件:
var animal = { eats: true } rabbit = Object.create(animal) alert(rabbit.eats) // true
上面程式碼建立了一個空rabbit對象,並且原型設定為animal
rabbit物件建立好以後,我們可以往裡面加入屬性了:
var animal = { eats: true } rabbit = Object.create(animal) rabbit.jumps = true
Object.creat函數的第二個參數props是可選的,它允許像新物件設定屬性。這裡就省略了,因為我們關係的繼承。
(1)Object.getPrototypeOf(obj)
傳回obj.__proto__的值。這個函數是標準的,可以在不能直接存取__proto__屬性的瀏覽器中使用了。
var animal = { eats: true } rabbit = Object.create(animal) alert( Object.getPrototypeOf(rabbit) === animal ) // true
現代瀏覽器允許讀取__proto__屬性值,但是不能設定。
3. The prototype
有一些好的跨瀏覽器的方式來設定__proto__屬性,這將會使用建構器函數(constructor functions)。記住!任何函數建立一個物件都是透過new關鍵字的。
一個栗子:
function Rabbit(name) { this.name = name } var rabbit = new Rabbit('John') alert(rabbit.name) // John
new操作將原型的屬性設定到rabbit物件的__proto__屬性中了。
讓我們來看看它的原理,例如,new Rabbit 對象,而Rabbit是繼承animal 的。
var animal = { eats: true } function Rabbit(name) { this.name = name } Rabbit.prototype = animal var rabbit = new Rabbit('John') alert( rabbit.eats ) // true, because rabbit.__proto__ == animal
Rabbit.prototype = animal 字面量表示:對所有由new Rabbit建立的物件設__proto__ = animal
4. 跨瀏覽器 Object.create(proto)
Object.create(prop)函數功能的強大的,因為它允許從給定的物件直接繼承。它可以由以下程式碼模擬:
function inherit(proto) { function F() {} F.prototype = proto return new F }
inherit(animal) 與Object.create(animal)是完全等同的,傳回一個空的對象,並且object.__proto__ = animal。
一個栗子:
var animal = { eats: true } var rabbit = inherit(animal) alert(rabbit.eats) // true alert(rabbit.hasOwnProperty('eats')) // false, from prototype
來看它的原理是什麼:
function inherit(proto) { function F() {} // (1) F.prototype = proto // (2) return new F() // (3) }
(1) 创建了一个新函数,函数没有向this设置任何属性,以此`new F` 会创建一个空对象。
(2) `F.prototype`被设置为proto
(3) `new` F创建了一个空对象,对象的`__proto__ = F.prototype`
(4) Bingo! 我们得到了一个继承`proto`的空对象
这个函数广泛适用于各种库和框架之中。
你的函数接受了一个带有options 的对象
/* options contains menu settings: width, height etc */ function Menu(options) { // ... } 你想设置某些options function Menu(options) { options.width = options.width || 300 // set default value // ... }
。。。但是改变参数值可能会产生一些错误的结果,因为options可能会在外部代码中使用。一个解决办法就是克隆options对象,复制所有的属性到一个新的对象中,在新对象中修改,
怎样用继承来解决这个问题呢? P.S. options可以添加设设置,但是不能被删除。
Solution
你可以继承options,并且在它的子类的中修改或者添加新的属性。
function inherit(proto) { function F() {} F.prototype = proto return new F } function Menu(options) { var opts = inherit(options) opts.width = opts.width || 300 // ... }
所有的操作只在子对象中有效,当Menu方法结束时,外部代码仍然可以使用没有修改的过的options对象。delete操作在这里非常重要,如果width是一个prototype中的属性,delete opts.width不会产生任何作用
5. hasOwnProperty
所有的对象都有hasOwnProperty函数,它可以用来检测一个属性是否对象自身还是属于原型
一个栗子:
function Rabbit(name) { this.name = name } Rabbit.prototype = { eats: true } var rabbit = new Rabbit('John') alert( rabbit.hasOwnProperty('eats') ) // false, in prototype alert( rabbit.hasOwnProperty('name') ) // true, in object
6. Looping with/without inherited properties
for..in循环输出一个对象的所有属性,包括自身的和原型的。
function Rabbit(name) { this.name = name } Rabbit.prototype = { eats: true } var rabbit = new Rabbit('John') for(var p in rabbit) { alert (p + " = " + rabbit[p]) // outputs both "name" and "eats" }
用hasOwnProperty可以过滤得到属于对象自己的属性:
function Rabbit(name) { this.name = name } Rabbit.prototype = { eats: true } var rabbit = new Rabbit('John') for(var p in rabbit) { if (!rabbit.hasOwnProperty(p)) continue // filter out "eats" alert (p + " = " + rabbit[p]) // outputs only "name" }
7. Summary
JavaScript是通过一个特殊的属性proto来实现继承的
当访问一个对象的属性时,如果解释器不能在对象中找到,它就会去对象的原型中继续寻找 对函数属性来说,this指向这个对象,而不是它的原型。
赋值obj.prop = value, 删除delete obj.prop
管理proto:
Chrome和FireFox可以直接访问对象的__proto__属性,大多数现代浏览器支持用Object.getPrototypeOf(obj)只读访问。
Object.create(proto) 可以用给定的proto生成空的子对象,或者通过如下代码达到相同的功能:
function inherit(proto) { function F() {} F.prototype = proto return new F() }
其他方法:
for..in循环输出一个对象的所有属性(包括自身的和原型的)和对象的原型链。
如果一个属性prop属于对象obj那么obj.hasOwnProperty(prop)返回true,否则返回false。

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1
強大的PHP整合開發環境

Atom編輯器mac版下載
最受歡迎的的開源編輯器

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。