JS基礎:Function.prototype函數原型的三個方法

news/2024/7/19 13:29:59 标签: js, javascript

JS 基礎:Function.prototype 三大方法

文章目錄

  • JS 基礎:Function.prototype 三大方法
    • 簡介
    • 參考
  • 正文
    • 目的
    • `Function.prototype.call` & `Function.prototype.apply`
      • call & apply 語法
      • call & apply Sample
    • `Function.prototype.bind`
      • bind 語法
      • bind Sample
    • 應用
      • self 替換
      • bind 函數
      • arrow function 箭頭函數
  • 結語

簡介

Function.prototype 有三個經典的方法調用,分別是 callapplybind,一言以蔽之就是綁定調用上下文,接下來就快速進入三個方法介紹。

參考

函數原型最實用的 3 個方法 — call、apply、bindhttps://medium.com/@realdennis/javascript-%E8%81%8A%E8%81%8Acall-apply-bind%E7%9A%84%E5%B7%AE%E7%95%B0%E8%88%87%E7%9B%B8%E4%BC%BC%E4%B9%8B%E8%99%95-2f82a4b4dd66
Function.prototypehttps://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype

正文

目的

首先我們先明確這三個函數的目的,我們都知道 function 關鍵字定義的一般函數會以調用者或調用環境作為上下文,也就是運行時動態綁定 this,這時候容易出現回調函數沒有正確綁定到上下文的情況(用過 React 的人一定對這行代碼不陌生:this.xxx = this.xxx.bind(this)),以下我們就來講解 callapplybind 用法上的意義和區別

Function.prototype.call & Function.prototype.apply

callapply 幾乎完全一樣,除了傳入參數的形式略有差異

call & apply 語法

js">// call 語法
func.call(ctx[, arg1[, arg2[, ...]]])

// apply 語法
func.apply(ctx, [argArray])
  • 說明:ctx 作為調用上下文為必選參數,而後面參數傳入的形式,call 逐個傳入參數;而 apply 則接受一個參數數組

call & apply Sample

js">function hi(a, b, c) {
  console.log(`Hello my name is ${this.name}`)
  console.log(`a = ${a}`)
  console.log(`b = ${b}`)
  console.log(`c = ${c}`)
}
let person = { name: 'John' }
let a = 1,
  b = 2,
  c = 3
hi.call(person, a, b, c)
// Hello my name is John
// a = 1
// b = 2
// c = 3

hi.apply(person, [a, b, c])
// Hello my name is John
// a = 1
// b = 2
// c = 3
  • 說明:hi 方法需要接受多個參數,同時內部調用 this.name 屬性,這時候的 this 對象就是 call 或 apply 傳入的第一個參數也就是 person 對象。也就是說下列的調用形式等價:
js">func.call(ctx, arg1, arg2, arg3)
// 等價於
func.apply(ctx, [arg1, arg2, arg3])
// 等價於
let ctx = {
  // some properties...
  func
}
ctx.func(arg1, arg2, arg3)

說實在使用上差異不大,最重要的差別可能要涉及到函數調用時的運行時機制,以及函數處理等。後續更進階可能還會用到 Thunk 函數、柯里化函數等手段,因此不需要在 call 和 apply 上過於糾結。

Function.prototype.bind

顧名思義就是一個“綁定”方法,這個方法的作用就是返回一個綁定了上下文環境的函數

bind 語法

js">func.bind(ctx) // 返回綁定了上下文還的境函數

bind Sample

延續剛剛用過的例子,這次我們先綁定好上下文環境之後就可以直接調用了:

js">function hi(a, b, c) {
  console.log(`Hello my name is ${this.name}`)
  console.log(`a = ${a}`)
  console.log(`b = ${b}`)
  console.log(`c = ${c}`)
}
let person = { name: 'John' }
let a = 1,
  b = 2,
  c = 3

hi = hi.bind(person)
hi(a, b, c)
  • 說明:由於 hi 方法已經被替換成綁定 person 的版本,因此調用的時候 this 就固定指向 person 對象而不是全局對象

應用

其實通常在寫業務邏輯的時候,比較少情況會出現 this 對象錯誤或非預期綁定的情況。更多的時候是出現在維護遺留項目(legacy project)的時候,想要複用過往的代碼,這時候我們可以有三種修改綁定的方法(詳見參考一鏈結)

self 替換

在函數內部使用 self 保留當前環境的 this 指針

js">let obj = {
  name: 'John',
  someFunc() {
    const self = this
    setTimeout(function () {
      console.log(`Hello my name is ${self.name}`)
    }, 1000)
  }
}
obj.someFunc()
  • 說明:如果沒有用 self 保留 this 指針的話,由於事件循環機制(Event Loop)會使得真正調用函數時的 this 指向全局對象,所以我們需要用保留下來的 self 來取代原本要引用的 this

bind 函數

我們也可以用本篇說到的 bind 函數在定義時就先綁定好上下文環境:

js">let obj = {
  name: 'John',
  someFunc() {
    setTimeout(
      function () {
        console.log(`Hello my name is ${this.name}`)
      }.bind(this),
      1000
    )
  }
}
obj.someFunc()

arrow function 箭頭函數

ES6 其實已經為這種情況提供語法糖,也就是箭頭函數的實現:

js">let obj = {
  name: 'John',
  someFunc() {
    setTimeout(() => {
      console.log(`Hello my name is ${this.name}`)
    }, 1000)
  }
}
obj.someFunc()
  • 說明:在之前的ES6 特性:箭頭函數篇就已經介紹過,箭頭函數的 this 在聲明時就會直接綁定到當前對象也就是 obj 對象

結語

本篇簡單介紹了 Function.prototype 的三大方法,本質上都是在處理上下文環境的綁定,可以在調用時指定上下文環境(call、apply)、也可以直接返回一個綁定好上下文環境的新函數(bind),縱然這三個方法非常基礎,卻是使用時容易忽略的技術細節,也是其他高階用法的基礎。


http://www.niftyadmin.cn/n/735648.html

相关文章

eggjs和dubbo结合,egg-dubbo-plugin的开发

由于MVC中的M都是dubbo服务,所以需要一个插件来调用dubbo服务。个人推荐这个包node-zookeeper-dubbo 我们所需要的只是把他封装成一个插件,使用方式则类似于httpClient. 首先执行egg-init --typeplugin egg-dubbo-plugin这样一个插件的大体框架就构造完成…

概率相关概念

一、概率论 概率空间:由三元组(Ω,F,P)定义: Ω是所有可能输出(样本点)的非空集合,称作样本空间.F是样本空间Ω幂集的非 空子 集, F⊆2ΩF\subseteq 2^{\varOmega}F⊆2Ω,称作事件空间. P称为概率 ,是一个从F到实数域…

JVM基本结构详解

2019独角兽企业重金招聘Python工程师标准>>> 什么是Java虚拟机 此处涉及到两个概念: Java虚拟机,相当于我们定义的Java类Java虚拟机实例,相当于new一个Java类注意:Java虚拟机通过java.exe或javaw.exe来启动一个Java虚拟…

JS基礎:DOM(Document Object Model) BOM(Browser Object Model)

JS 基礎:DOM & BOM 文章目錄JS 基礎:DOM & BOM簡介參考正文Overview 總覽BOM(Browser Object Model)Window 對象Window.document (Document 對象)Window.history (History 對象)Window.location (Location 對象)Window.navigator (Navigator 對象…

多元回归模型

回归模型 1 基本知识介绍 1.1回归模型的引入 由于客观事物内部规律的复杂性及人们认识程度的限制,无法分析实际对象内在的因果关系,建立合乎机理规律的数学模型。所以在遇到有些无法用机理分析建立数学模型的时候,通常采取搜集大量数据的办法…

js-cookie:轻量级 cookie 框架

js-cookie:轻量级 cookie 框架 文章目錄js-cookie:轻量级 cookie 框架簡介參考正文Import 引入方法CDNNPMjs-cookie 接口說明三種基本方法語法避免衝突Cookie Attribute 屬性說明1. expires 屬性2. path 屬性3. domain 屬性4. secure 屬性5. sameSite 屬…

扩展欧几里得和中国剩余定理

贴一个dalao的证明:欧几里德算法与扩展欧几里德算法 1.欧几里得算法 O(logn) int gcd(int a,int b) {if(!b){return b;}return gcd(b,a%b); }2.贝祖定理 正整数a,b,那么一定存在非零整数x,y使得axbygcd(a,b) 构造法证明——扩展欧几里得算法 贝祖定理…

使用Android注解处理器,解放劳动生产力

“我已放弃成为珠三角头发最浓密的程序员梦想...” 简介 在android开发中,比较常用到的第三方库中,有不少用到了 注解处理器(Annotation Processor)。 比较常见的就有 Butterknife,Dagger2,DBFlow 等。 注解 Java中存在不少关于注…