搜尋
首頁web前端js教程淺談javascript的call()、apply()、bind()的用法_javascript技巧

JavaScript中的函數不僅是一種類似Java中方法的語言功能,它還可以作為物件而存在。 本文將要探討JavaScript中函數的一些特殊用法,包括call、apply、bind三個原型方法。
一、函數基礎
JavaScript中的函數是一種類似Java中方法的語言功能,不過它可以獨立於類別來定義。

函數式程式設計:由於JavaScript支援匿名函數,因此可以將函數當作物件來使用, 所以JavaScript不僅支援過程式設計(物件導向也是過程式程式設計的一種),也支援函數式程式設計。
上下文

函數的每次呼叫都會擁有一個特殊值-本次呼叫的上下文(context)-這就是this關鍵字的值。 如果函數掛載在一個物件上,作為物件的屬性,就稱它為物件的方法。當透過這個物件來呼叫函數時,該物件就是此次呼叫的上下文, 也就是該函數的this的值。

要注意,this是一個關鍵字,不是變量,也不是屬性名稱。 JavaScript的語法不允許給this賦值。

函數是一種物件

JavaScript中的函數和Java中的方法或C語言中的函數最大不同在於,JavaScript中的函數也是一種物件。 但這並不意味著,所有的物件都是函數。函數是一種包含了可執行程式碼,並能夠被其他程式碼呼叫的特殊的物件。

和變數不同,關鍵字this沒有作用域的限制,巢狀的函數不會從呼叫它的函數繼承this。 - 如果巢狀函數作為方法調用,其this的值指向調用它的物件。 - 如果巢狀函數作為函數調用,其this的值不是全域物件(非嚴格模式下)就是undefined(嚴格模式下)。

很多人誤以為呼叫巢狀函數時this會指向掉i用外層函數的上下文。如果你想要存取這個外部函數的this值, 需要將this的值保存都在一個變數中,這個變數和內部函數都同在一個作用域內。例如:

var o = {
 m: function() {
  var self = this;
  console.log(this==o); // true
  f();
  
  function f() {
   console.log(this === o); // false,this的值是全局对象或undefined
   console.log(self === o); // true
  }
 }
}

閉包

JavaScript的函數可以嵌套在其他函數中定義,這樣它們就可以存取它們被定義時所處的作用域中的任何變數。 這意味著JavaScript函數構成了一個閉包(closure),它為JavaScript帶來了非常強勁的程式設計能力。

作為值的函數
在JavaScript中,函數不僅是一種語法,也是值,也就是說,可以將函數賦值給變量,儲存在物件的屬性或陣列的元素中, 作為參數傳入另外一個函數等。

bind、call、apply
每一個函數都包含一個prototype屬性,這個屬性是指向一個物件的引用,這個物件稱為「原型物件」。 每一個函數都包含不同的原型物件。當將函數用作建構函數的時候,新建立的物件會從原型物件上繼承屬性。

Function.prototype.call()Function.prototype. >

call()和apply()可以看作為某個物件的方法,透過呼叫方法的形式來間接呼叫函數。 它們的第一個參數是要呼叫函數的母對象,它是呼叫上下文,在函數體內透過this來獲得對它的參考。 apply()方法和call()方法的作用相同,只不過函數傳遞的方式不一樣,它的實參都放入在一個陣列中。

舉個例子,以物件o的方法的形式呼叫函數f(),並傳入兩個參數,可以使用這樣的程式碼:

var o = {};

function f(a, b) {
 return a + b;
}

f.call(o, 1, 2);    // 将函数f作为o的方法,实际上就是重新设置函数f的上下文
f.apply(o, [1, 2]);
再舉一個例子,使用call方法呼叫匿名函數:

在下例中的for迴圈體內,我們建立了一個匿名函數,然後透過呼叫函數的call方法,將每個陣列元素作為指定的this值執行了那個匿名函數。 這個匿名函數的主要目的是為每個數組元素物件添加一個print方法,這個print方法可以列印出各元素在數組中的正確索引號。 當然,這裡不是必須讓陣列元素作為this值傳入那個匿名函數(普通參數就可以),目的是為了示範call的用法。

var animals = [
 {species: 'Lion', name: 'King'},
 {species: 'Whale', name: 'Fail'}
];

for (var i = 0; i < animals.length; i++) {
 (function (i) { 
  this.print = function () { 
   console.log('#' + i + ' ' + this.species + ': ' + this.name); 
  } 
  this.print();
 }).call(animals[i], i);
}

Function.prototype.bind()

bind()是在ES5中新增的方法,從名字可以看出,這個方法的主要作用就是將函數綁定到某個物件。 當在函數f()上呼叫bind()方法併後竄入一個物件o作為參數,這個方法將傳回一個新函數:(以函數呼叫的方式)呼叫新的函數將會將原始的函數f()作為o的方法來呼叫。例如:

function f(y) {
 return this.x + y;
}

var o = {
 x: 1
};

var g = f.bind(o); // 通过调用 g(x) 来调用 o.f(x)
g(2); // 3

其實我們可以輕鬆的實作bind()方法:

// 返回一个函数,通过调用它来调用o中的方法f(),传递它所有的实参
function bind(f, o) {
 if (f.bind) return f.bind(o); // 如果bind()方法存在,使用bind()方法
 else return function () {
  return f.apply(o, arguments);
 }
}

二、函数式编程
JavaScript并非函数式编程语言,但在JavaScript中可以像操控对象一样操控函数,也就是说可以在JavaScript中应用函数式编程技术。

使用函数处理数组

假设有一个数组,数组元素都是数字,我们想要计算这些元素的平均值和标准差。

var data = [1, 1, 3, 5, 5];
var sum = function(x, y) {
 return x + y;
};
var square = function(x) {
 return x * x;
};

var mean = data.reduce(sum)/data.length;
var deviations = data.map(x => x - mean);

var stddev = Math.sqrt(deviations.map(square).reduce(sum)/(data.length - 1));
高阶函数

高阶函数就是操作函数的函数,它接收一个或多个函数作为参数,并返回一个新函数。举个例子:

function not(f) {
 return function () {
  var result = f.apply(this, arguments);
  return !result;
 };
}

// 判断x是否为偶数的函数
var even = function(x) {
 return x % 2 === 0;
};

var odd = not(even);      // 一个新函数,所做的事情和even()相反
[1, 1, 3, 5, 5].every(odd);   // true,每个函数都是奇数

函数not()是个高阶函数,因为它返回一个新的函数,这个新函数将它的实参传入f(),并返回f的返回值的逻辑非。

以上就是关于javascript的call()、apply()、bind()的用法,希望对大家的学习有所帮助。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具