摘要:上一章前端教學(xué)講義基礎(chǔ)閉包高階函數(shù)閉包是一種打通兩個作用域的能力,在和中都有類似的功能,中的閉包和他們沒有太大的差別。在中任何函數(shù)都可以當作構(gòu)造函數(shù)并搭配關(guān)鍵詞使用。再將作為運行構(gòu)造函數(shù)。
上一章:前端教學(xué)講義:JS基礎(chǔ)
閉包、高階函數(shù)閉包是一種打通兩個作用域的能力,在 Java 和 OC 中都有類似的功能,JS 中的閉包和他們沒有太大的差別。
不過因為 JS 的函數(shù)是一等公民,所以使用起來會更加靈活。
在數(shù)學(xué)和計算機科學(xué)中,高階函數(shù)是至少滿足下列一個條件的函數(shù):
接受一個或多個函數(shù)作為輸入
輸出一個函數(shù)
下面的例子就是個典型的高階函數(shù)
const multiple = function(a, b) { return a * b; } const plus = function(a, b) { return a + b; } const express = function(operator, a, b) { return operator(a)(b); } [ [plus, 1, 2], [multiple, 3, 4], ].map(function(formula) { return express.apply(null, formula) }); // [3, 12]call,apply,bind
在 JS 中經(jīng)常會遇到 this 指向錯亂的問題:
var obj = { value: 1234, log: function() { console.log(this.value) } } var log = obj.log; log(); // 這個函數(shù)執(zhí)行的時候沒有上下文,this 會默認為 window 或者 global // undefined
JS 提供了兩個方法,call 和 apply,能夠指定一個函數(shù)執(zhí)行時候的上下文
log.call(obj); // 1234 log.apply(obj); // 1234
call 和 apply 同時還可以指定傳給函數(shù)的參數(shù)是什么,他們的區(qū)別就是后面的傳參數(shù)形式不一樣;
function fn(arg1, arg2){} fn.call(obj, arg1, arg2) fn.apply(obj, [arg1, arg2]) // apply 是將參數(shù)當作數(shù)組傳入
bind 函數(shù)通過閉包的形式,來強制的將某個上下文綁定到函數(shù)上:
log = bind(log, obj); // 返回一個新函數(shù),此函數(shù)的 this 強制被綁定為 obj log() 1234
bind 的實現(xiàn)大概如下(省略傳參的功能):
function bind(fn, ctx) { return function() { return fn.apply(ctx); } }
和上面舉例有點區(qū)別的是 JS 提供的 bind 方法是 Function 類的一個方法,調(diào)用方法如下:
function log() {} log = log.bind(obj)原型鏈
JS 的原型鏈(prototype chain)是為了實現(xiàn)面向?qū)ο蠖嬖诘?,當訪問一個對象的方法的時候,首先會遍歷對象本身,是否存在這個鍵,然后在查找父類是否有這個鍵,再一直追溯到頂層。
「父類」中包含的方法和屬性,都存放在對象的 「__proto__」對象上(在舊的 JS 規(guī)范中,「__proto__」是隱藏屬性,但是 ES6 將它標準化并暴露出來了)。
var c = { somekey: 1, } var b = { __proto__: c, } var a = { __proto__: b } a.somekey // 1
當訪問 「a.somekey」 的時候,會沿著原型鏈一直向上查找,相當于做了如下計算:
function getValue(obj, key) { while (obj) { if (key in obj) { return obj[key] } if (obj.__proto__) { obj = obj.__proto__; } else { return undefined; } } } getValue(a, "somekey")類
在最早期的 JS 版本中是沒有類的,后來加入了原型鏈和 new 關(guān)鍵詞才實現(xiàn)了類。
function SubClass(value) { this.value = value; } SubClass.prototype = { log: function() { console.log(this.value); } } var sub = new SubClass(1234); sub.log(); // 1234
在 JS 中任何函數(shù)都可以當作構(gòu)造函數(shù)并搭配 new 關(guān)鍵詞使用。
new 關(guān)鍵詞的作用就是新建一個空對象 a,然后把構(gòu)造函數(shù)上的 prototype 值掛載到 a.__proto__ 上。
再將 a 作為 context 運行構(gòu)造函數(shù)。
如果我們將 new 作為一個函數(shù),它就是這樣:
function new(class, ...params) { var instance = {}; instance.__proto__ = class.prototype; var result = class.apply(instance, params); if (typeof result !== "undefined") { return result; } return instance; } var sub = new(SubClass, 1234);
從上面的代碼可以看出,在構(gòu)造函數(shù)中,可以指定 new 關(guān)鍵詞返回的類型,也就是說 new A() 返回的結(jié)果不一定就是 A 的實例,這要看 A 的構(gòu)造函數(shù)內(nèi)部是如何實現(xiàn)的。
function A() { return 1234; } var a = new A(); console.log(a) // 1234
JS 用原型鏈的方式,曲線的實現(xiàn)了類的行為和寫法,所以在 JS 中,「類」就是構(gòu)造函數(shù)。
instanceof如何判斷一個對象是否是一個類的實例呢?
JS 實現(xiàn)的方法很粗糙,就是判斷實例的原型鏈上是否存在類的原型。
function A() { } var a = new A(); a instanceof A true
我們甚至可以讓任意一個類成為實例的父類
function C() {} function A() {} var a = new A(); C.prototype = A.prototype; a instanceof A // true a instanceof C // true
我們甚至也可以讓一個父類不是實例的父類
function A() {} var a = new A(); A.prototype = {}; // 對原型重新賦值 a instanceof A false
總之就是很神奇
ES6 中對類的改進在 ES6 中新增了 class 關(guān)鍵詞,使得聲明一個類更加簡單,但只是寫法上有改變,運行機制還是一樣。
class A { constructor(value) { this.value = value; } log() { console.log(this.value); } } var a = new A(1234); a.log(); // 1234
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96139.html
摘要:春招前端實習(xí)面試記錄從就開始漸漸的進行復(fù)習(xí),月末開始面試,到現(xiàn)在四月中旬基本宣告結(jié)束。上海愛樂奇一面盒模型除之外的面向?qū)ο笳Z言繼承因為是視頻面試,只記得這么多,只感覺考察的面很廣,前端后端移動端都問了,某方面也有深度。 春招前端實習(xí)面試記錄(2019.3 ~ 2019.5) 從2019.1就開始漸漸的進行復(fù)習(xí),2月末開始面試,到現(xiàn)在四月中旬基本宣告結(jié)束。在3月和4月經(jīng)歷了無數(shù)次失敗,沮...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細介紹 HTT...
摘要:可能因為先入為主,在編程之中,往往不由自主地以的邏輯編程思路設(shè)計模式進行開發(fā)。這是原型模式很重要的一條原則。關(guān)于閉包與內(nèi)存泄露的問題,請移步原型模式閉包與高階函數(shù)應(yīng)該可以說是設(shè)計模式的基礎(chǔ)要領(lǐng)吧。在下一章,再分享一下的幾種常用設(shè)計模式。 前 在學(xué)習(xí)使用Javascript之前,我的程序猿生涯里面僅有接觸的編程語言是C#跟Java——忽略當年在大學(xué)補考了N次的C與VB。 從靜態(tài)編程語言,...
講義內(nèi)容:JS 誕生的背景、基本類型、運算符 以下內(nèi)容只涉及 ES5 標準,ES6 增加的新內(nèi)容可以在網(wǎng)上查找到。 JS 誕生的背景 上世紀 90 年代網(wǎng)景公司開發(fā)的瀏覽器獨步天下 一個叫做 Brendan Eich 的工程師受命于開發(fā)一款腳本語言,來增強瀏覽器的功能。 這名工程師花費了 10 天時間設(shè)計出了第一個版本,名叫 LiveScript。 后來因為當時 Java 正紅,公司將其改名為 J...
摘要:引言本期開始介紹中的高階函數(shù),在中,函數(shù)是一種特殊類型的對象,它們是。簡單來說,高階函數(shù)是一個接收函數(shù)作為參數(shù)傳遞或者將函數(shù)作為返回值輸出的函數(shù)。我們來看看使用它們與不使用高階函數(shù)的方案對比。引言 本期開始介紹 JavaScript 中的高階函數(shù),在 JavaScript 中,函數(shù)是一種特殊類型的對象,它們是 Function objects。那什么是高階函數(shù)呢?本節(jié)將通過高階函數(shù)的定義來展...
閱讀 1712·2021-11-12 10:35
閱讀 1643·2021-08-03 14:02
閱讀 2717·2019-08-30 15:55
閱讀 2056·2019-08-30 15:54
閱讀 797·2019-08-30 14:01
閱讀 2453·2019-08-29 17:07
閱讀 2284·2019-08-26 18:37
閱讀 3059·2019-08-26 16:51