成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

前端教學(xué)講義:閉包、高階函數(shù)、原型鏈

meislzhua / 3502人閱讀

摘要:上一章前端教學(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

相關(guān)文章

  • 2019春招前端實習(xí)面經(jīng)總結(jié)

    摘要:春招前端實習(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ù)次失敗,沮...

    atinosun 評論0 收藏0
  • JS筆記

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細介紹 HTT...

    rottengeek 評論0 收藏0
  • JavaScript設(shè)計模式

    摘要:可能因為先入為主,在編程之中,往往不由自主地以的邏輯編程思路設(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)編程語言,...

    keke 評論0 收藏0
  • ?前端教學(xué)講義:JS基礎(chǔ)

    講義內(nèi)容:JS 誕生的背景、基本類型、運算符 以下內(nèi)容只涉及 ES5 標準,ES6 增加的新內(nèi)容可以在網(wǎng)上查找到。 JS 誕生的背景 上世紀 90 年代網(wǎng)景公司開發(fā)的瀏覽器獨步天下 一個叫做 Brendan Eich 的工程師受命于開發(fā)一款腳本語言,來增強瀏覽器的功能。 這名工程師花費了 10 天時間設(shè)計出了第一個版本,名叫 LiveScript。 后來因為當時 Java 正紅,公司將其改名為 J...

    walterrwu 評論0 收藏0
  • 【進階 6-1 期】JavaScript 高階函數(shù)淺析

    摘要:引言本期開始介紹中的高階函數(shù),在中,函數(shù)是一種特殊類型的對象,它們是。簡單來說,高階函數(shù)是一個接收函數(shù)作為參數(shù)傳遞或者將函數(shù)作為返回值輸出的函數(shù)。我們來看看使用它們與不使用高階函數(shù)的方案對比。引言 本期開始介紹 JavaScript 中的高階函數(shù),在 JavaScript 中,函數(shù)是一種特殊類型的對象,它們是 Function objects。那什么是高階函數(shù)呢?本節(jié)將通過高階函數(shù)的定義來展...

    yiliang 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<