<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
瀏覽下文我覺得還是要有些基礎的!下文涉及的知識點太多,基本上每一個拿出來都能寫幾篇文章,我在寫文章的過程中只是做了簡單的實現,我只是提供了一個思路,更多的細節還是需要自己去鑽研的,文章內容也不少,辛苦,如果有其他的看法或者意見,歡迎指點,最後紙上得來終覺淺,絕知此事要躬行
javscript 一切皆為物件,但基本型別之外,函數是物件,物件是由函數建立而來, 從而衍生出我對這兩種程式設計方式的探討。下面對型別判斷和原型做了一個簡單的表述,這裡不是重點,不做具體的表述,感興趣的可以自己百度/谷歌。
// 型別判斷 // 基本型別 console.log(typeof 1) // | ==> number console.log(typeof '2') // | ==> string console.log(typeof undefined) // | ==> undfined // null 型別判斷【特殊】 console.log(typeof null) // | ==> object console.log(Object.prototype.toString.call(null)) // | ==> [object Null] // 報錯【null 不是一個物件】TypeError: Right-hand side of 'instanceof' is not an object console.log(null instanceof null) console.log(typeof Symbol()) // | ==> symbol 【ES6 新型別】 console.log(typeof false) // | ==> boolean console.log(typeof BigInt(9007199254740991n)) // | ==> bigint 【新型別】 // 參照型別 - 物件 console.log(typeof (() => {})) // | ==> function console.log((() => {}) instanceof Object) // true console.log(typeof []) // | ==> object console.log(typeof {}) // | ==> object console.log(typeof (/./)) // | ==> object console.log(typeof new Date()) // | ==> object console.log(typeof new String()) // | ==> object console.log(typeof new Number()) // | ==> object
// 原型鏈 // fn ====> function fn () {} // Object ====> function Object () {} // Function ====> function Funtion() new fn() - __proto__ --| ↑ ↓ ---→ fn ----------- fn.prototype -------- __proto__ -----→ Object.prototype -- __proto__--→ null | ↑ |--------- __proto__ ------→ Function.prototype --- __proto__ -----| ↑ Function -------→ __proto__ | Object
在物件導向程式設計中最常見的表現形式就是類,提供了物件導向的 3⃣ 大特點和 5⃣️ 大原則,這東西網上特別多,我只做簡單的羅列,下面我會對特點進行實現,我的理解: 原則是物件導向程式設計的規範,而特點是物件導向程式設計的實現,前提是你已經仔細理解過下面對核心概念。
三大特點
五大原則
繼承是物件導向一個特點,可以實現子類呼叫自己沒有的屬性方法【父類別屬性方法】
/** ES6 **/ class Parent {} class Child extends Parent { constructor () { super() } } /** ES5 **/ function parent () { this.run () {} } parent.prototype.eat = function () {} function child () {} // 原型式繼承 child.prototype = parent.prototype child.prototype.constructor = child // 原型鏈繼承 child.prototype = new parent() child.prototype.constructor = child // 構造器繼承 function boyChild (..arg) { parent.apply(this, arg) } // 組合繼承 function boyChild (..arg) { parent.apply(this, arg) } boyChild.prototype = new parent() child.prototype.constructor = child // 寄生組合繼承 function child (..arg) { parent.apply(this, arg) } // ${1} ( function () { function transmit () {}; transmit.prototype = parent.prototype child.prototype = new prototype() child.prototype.constructor = child } )() // ${2} child.prototype = Object.create(parent.prototype) // ...... // 總結 // 繼承的方式方法多種多樣,不外乎,就是通過,某一種方式將不屬於自己的屬性方法可以呼叫,沿著原型的方式和拷貝賦值就可以總結出很多種不同的繼承方式,每種方式的優缺點,多是考慮,繼承的屬性方法的完整性和對範例化物件的影響,如範例上方法和原型鏈上方法是否都可以呼叫有或者參照傳遞改變同一原型鏈問題。
/** 上面為對範例對繼承,下面說一說對於介面對繼承 **/ // ES6 中並沒有提供介面這個概念,但是 Typescript 中對於介面又很好對支援,typescript 是 javascript 對超集,對物件導向提供了非常好對支援 // Typescript 【一時用一時爽,一直用一直爽】 // 很推薦用這個,他能避免很多低階錯誤,提供型別檢查,特別是寫過 java 轉前端的。 interface parent { run: () => void } class child implements parent { run () {} } // 轉碼後 var child = /** @class */ (function () { function child() { } child.prototype.run = function () { }; return child; }());
多型是物件導向一個特點,可以實現子類有不同對錶現形態,可以實現同一種表現形式,可以有不同對狀態
/** ES6 **/ // ${1} 重寫 class Animal { eat () { console.log('animal eat') } } class Pig extends Animal { constructor () { super() } eat () { console.log('pig eat grass') } } class Tiger extends Animal { constructor () { super() } eat () { console.log('tiger eat pig') } } // ${2} 過載,模擬實現 class Animal { eat () { if (typeof arg === '') { console.log('操作 one') } else if (typeof arg === '') { console.log('操作 two') } else { console.log('操作 three') } } } /** ES5 【提供實現一種】**/ // 原理就是沿著原型鏈往上找,只要在父類別前定義重寫這個方法即可 // ${1} 重寫 function animal () { this.eat = function () { console.log('Animal eat') } } function pig () { animal.call(this) this.eat = function () { console.log('pig eat grass') } } function tiger () { animal.call(this) this.eat = function () { console.log('tiger eat pig') } } // ${2} 過載 function animal () { eat () { if (typeof arg === '') { console.log('操作 one') } else if (typeof arg === '') { console.log('操作 two') } else { console.log('操作 three') } } }
封裝是物件導向一個特點,將屬性和方法封裝這物件中,可以利用私有或者公有屬性,對外提供可以存取的方法或屬性
/** ES6 **/ // ES6 沒有提供真正的私有方法和屬性,有一個還在提案階段 // 在屬性和方法前面加 # class Animal { #height = '' #eat () {} } // 模擬實現 【提供一種實現】 class Animal { constructor () { this.height = '50' } get height() { return undefined } set height (value) { return undefined } } /** ES5 **/ const animal = (function (arg) { let height = 50 function eat () {console.log(height)} return { eat } })([]) /** Typescript **/ class Animal { public height: number private name: string protected color: string constructor (height: number, name: string, color: string) { this.height = height this.name = name this.color = color } private eat ():void { console.log(this.name) } }
函數語言程式設計提倡函數是第一公民【指的是函數與其他資料型別一樣,處於平等地位,可以賦值給其他變數,也可以作為引數,傳入另一個函數,或者作為別的函數的返回值】,純粹的函數語言程式設計,是純函數【如果傳入的引數相同,就會返回相同的結果,不依賴於外部的資料狀態【如下範例】】,函數程式設計特點
// 純函數 const add = (one, two) => { return one + two } // 非純函數 let two = 1 const add = (one) => { return one + two }
閉包理解 函數內部還有其他函數,可以使父函數資料狀態得以儲存 高階函數理解 函數可以通過變數傳遞給其他函數
// 利用封包實現一個只能呼叫一次的 map 高階函數 const map = (fn) => { let once = false return (arr) => { return once? null: (once = true, arr.map(fn)) } } const fn = (item) => item + 10 const arrMap = map(fn) arrMap([1, 2, 3]) // [11, 12, 13] arrMap([4, 5, 6]) // null
柯里化理解 柯里化是將一個多元函數轉換為巢狀一元函數的過程
function curry (fn) { return curryN (...arg) { if (arguments.length < fn.length) { return function () { return curryN.call(null, ...arg.concat(...arguments)) } } return fn.call(null, ...arguments) } } const add = curry ((x, y, z) => x + y + z) console.log(add(2)(3)(4)) // 9
偏函數理解 初始化時指定原函數的一些引數並建立一個新函數,這個函數用於接收剩餘引數
function proto(fn, ...pagram) { return (...args) => { args.forEach((item, index) => { if (item && !pagram[index]) pagram[index] = item }) return fn.apply(null, pagram) } } let add = proto((x, y) => { console.log(x + y) }, undefined, 10) add(2) // 12
組合和管道理解 將一個函數的輸出作為另一個函數的輸入,像流水一樣從函數佇列從左到右流動或者從右到左流動
// 單個引數,簡單組合 const compose = (fn, fnc) => (arg) => fn(fnc(arg)) // 多個引數,藉助偏函數實現 function mapArr(arr, fn) { return arr.map(fn) } function filte (arr, fn) { return arr.filter(fn) } let map = proto(mapArr, undefined, (item) => { return item + 10 }) let filter = proto(filte, undefined, (item) => { return item }) let mapFilter = compose(map, filter) console.log(mapFilter([1, false, 9, 4])) // [11, 19, 14] // 多個函陣列合 const reduce = (arr, fn, value) => { let initValue = value? value: arr[0] arr.forEach((item) => { initValue += fn(initValue, item) }) return initValue } const compose = (...arg) => (value) => reduce(arg.reverse(), (acc, fn) => fn(acc), value) let add = compose(() => { return 1 }, () => { return 2 }, () => { return 3 }) add(6) // 12
函子的定義 函子是一個普通物件(在其他語言中,可能是一個類),它實現了 map 函數,在遍歷每個物件值的時候生成一個新物件 很抽象,簡單來說 函子是一個持有值的容器。嗨難懂,上程式碼。
// 實現一個基本定義的函子,滿足定義 // 實現 map 方法,在遍歷物件的時候生成一個新物件 function container (value) { this.value = value } container.prototype.of = function (value) { return new container(value) } container.prototype.map = function(fn) { return new container().of(fn(this.value)) } new container().of([1, 5, 7, 3]).map((arr) => { return arr.filter((item) => item === 5)}) console.log( new container().of([1, 5]).map((arr) => { return arr.filter((item) => item === 5)}).value ) // 5
到此物件導向和函數語言程式設計的基本思想就都簡單實現了,更多的需要自行深入學習
上面兩種程式設計方式在學習實踐的過程中給我提供了很多解決問題和組織程式碼框架的思維,在很多開源庫中也能看見它們實現的影子,當然真正理解這兩種程式設計方式,談何容易,更多的是要不斷的實踐和思考總結,慢慢積累
以上就是js物件導向程式設計OOP及函數語言程式設計FP區別的詳細內容,更多關於js物件導向OOP函數式FP區別的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45