摘要:碰過的一個(gè)有趣的問題實(shí)現(xiàn)一個(gè)構(gòu)造函數(shù),有一個(gè)屬性,每次調(diào)用該值加。共有方法看下面的代碼可以發(fā)現(xiàn),被重復(fù)創(chuàng)建了如果不想方法或者屬性在每次時(shí)新創(chuàng)建一份,可以將其設(shè)置在構(gòu)造函數(shù)的原型上。
面向?qū)ο笥腥齻€(gè)特點(diǎn),一個(gè)個(gè)來說:
封裝 私有變量利用閉包實(shí)現(xiàn)對(duì)象的私有變量。
function Animal (age) { this.getAge = function () { return age } } var dog = new Animal(3) console.log(dog.age) // undefined console.log(dog.getAge()) // 3
碰過的一個(gè)有趣的問題:
實(shí)現(xiàn)一個(gè)book構(gòu)造函數(shù),有一個(gè)屬性id,每次調(diào)用該值加1。
運(yùn)用閉包和立刻執(zhí)行函數(shù)。
let Book = (function () { let id = 1 return function () { this.id = id++ } })() let bok1 = new Book() let bok2 = new Book() let bok3 = new Book() console.log(bok3.id) // 3共有方法
看下面的代碼可以發(fā)現(xiàn),getAge被重復(fù)創(chuàng)建了
var dog = new Animal(3) var cat = new Animal(5) console.log(dog.getAge === dog.getAge) // false
如果不想方法或者屬性在每次new時(shí)新創(chuàng)建一份,可以將其設(shè)置在構(gòu)造函數(shù)的原型prototype上。
Animal.prototype.feed = function () { console.log("feed") } console.log(dog.feed === cat.feed) // true繼承
聽說繼承有六種方法,假設(shè)讓Dog繼承Animal,無非就是for in 復(fù)制屬性,修改原型鏈如dog.prototype = new Animal,直接Object.create,在Dog中使用Animal.call
然而我們記住最好的一種就夠了,就是組合繼承。
先試下這樣寫,利用call的繼承:
function Animal (name) { this.name = name; this.say = function() { console.log(this.name) } } // *1 function Dog (color, name) { Animal.call(this, name) this.color = color } // *2 let wangcai = new Dog("blue", "wangcai") console.log(wangcai) // {color: "blue", name: "wangcai") wangcai.say() // "wangcal"
可是如果在*1處加上這樣的代碼
Animal.prototype.say2 = function() { console.log(this.name) }
在*3處輸入
wangcai.say2(),會(huì)報(bào)錯(cuò)提示不存在該方法,說明我們的繼承是不完整的。dog沒有繼承原型鏈上的方法
我們需要在*2補(bǔ)上:
Dog.prototype = Object.create(Animal.prototype)
這時(shí)候不會(huì)報(bào)錯(cuò)了,補(bǔ)上Object.create的polyfill
function objectCreate (proto) { function F() {} F.prototype = proto; return new F(); }
然而還有一點(diǎn)小漏洞,當(dāng)我們查看wangcai.constructor時(shí),會(huì)發(fā)現(xiàn)指向的是Animal。因此我們需要修復(fù)一下:
Dog.prototype.constructor = Dog
補(bǔ)充一下new的模擬
function fNew (base) { var o = {} o.__proto__ = base.prototype base.call(o) return o }
完整代碼
function Animal (name) { this.name = name; this.say = function() { console.log(this.name) } } Animal.prototype.say2 = function () { console.log(this.name) } function Dog (color, name) { Animal.call(this, name) this.color = color } Dog.prototype = Object.create(Animal.prototype) Dog.prototype.constructor = Dog let wangcai = new Dog("blue", "wangcai")
檢測(cè)繼承是否成功的代碼:
console.log(wangcai instanceof Animal) console.log(wangcai instanceof Dog) console.log(wangcai.constructor === Dog) console.log(wangcai.say2 === Animal.prototype.say2) console.log(wangcai.__proto__ === Dog.prototype) console.log(wangcai.__proto__.__proto__ === Animal.prototype) console.log(wangcai.__proto__.__proto__.__proto__ === Object.prototype) console.log(wangcai.constructor === Dog)
使用Object.create()和修復(fù)Dog.prototype.constructor = Dog是不是挺多余的?es6提供了這么一個(gè)函數(shù)Object.setPrototypeOf.
因此我們可以使用
Object.setPrototypeOf(Dog.prototype, Animal.prototype)
替換剛剛提到的兩行代碼
可以了解到Object.setPrototypeOf(A,B)相當(dāng)于令A(yù).__proto__ = B。
多態(tài)一個(gè)函數(shù)可以應(yīng)用于不同的對(duì)象。并且根據(jù)this的不同,函數(shù)調(diào)用的結(jié)果也不同
function test() { alert([this.a, this.b]); } test.call({a: 10, b: 20}); // 10, 20 test.call({a: 100, b: 200}); // 100, 200 var a = 1; var b = 2; test(); // 1, 2
或是在函數(shù)中檢測(cè)arguments的數(shù)量和類型來實(shí)現(xiàn)多態(tài)
function add (a, b) { if (arguments.length === 2) { return a + b } else { return a + 1 } } console.log(add(1,4)) console.log(add(1))
END
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/95893.html
摘要:對(duì)于屬性來說類內(nèi)部的調(diào)用方式靜態(tài)屬性是類的屬性普通屬性是類具體實(shí)例化出的對(duì)象的屬性所以二者是完全不同的調(diào)用方式也非常不同靜態(tài)屬性靜態(tài)屬性名類名靜態(tài)屬性名普通屬性普通屬性名類外部的調(diào)用方式靜態(tài)屬性是類的屬性普通屬性是類具體實(shí)例化出的對(duì)象的屬 對(duì)于 屬性 來說 類內(nèi)部的調(diào)用方式 靜態(tài)屬性是類的屬性 普通屬性是類具體實(shí)例化出的對(duì)象的屬性 所以二者是完全不同的, 調(diào)用方式也非常不同 ...
摘要:面向?qū)ο笾饕R(shí)點(diǎn)小結(jié),基于構(gòu)造函數(shù)可以理解為通過即將創(chuàng)建的對(duì)象將類實(shí)例化給一個(gè)對(duì)象賦予屬性或者方法原型便于方法的重用與構(gòu)造函數(shù)模式相比,使用原型對(duì)象的好處是可以讓所有對(duì)象實(shí)例共享它所包含的屬性和方法。 JavaScript面向?qū)ο笾饕R(shí)點(diǎn)小結(jié),基于ECMAScript 5. 構(gòu)造函數(shù) function People(name){ //this可以理解為通過new即將創(chuàng)建...
摘要:參考鏈接面向?qū)ο缶幊棠P同F(xiàn)在的很多編程語言基本都具有面向?qū)ο蟮乃枷?,比如等等,而面向?qū)ο蟮闹饕枷雽?duì)象,類,繼承,封裝,多態(tài)比較容易理解,這里就不多多描述了。 前言 在我們的日常日發(fā)和學(xué)習(xí)生活中會(huì)常常遇到一些名詞,比如 命令式編程模型,聲明式編程模型,xxx語言是面向?qū)ο蟮牡鹊?,這個(gè)編程模型到處可見,但是始終搞不清是什么?什么語言又是什么編程模型,當(dāng)你新接觸一門語言的時(shí)候,有些問題是需...
閱讀 2115·2021-11-23 09:51
閱讀 2281·2021-09-29 09:34
閱讀 3767·2021-09-22 15:50
閱讀 3614·2021-09-22 15:23
閱讀 2717·2019-08-30 15:55
閱讀 758·2019-08-30 15:53
閱讀 3145·2019-08-29 17:09
閱讀 2696·2019-08-29 13:57