克服 JS 的奇怪部分:call()、bind()、apply()

这次一样来分享来自"克服 JS 的奇怪部分"的学习笔记,这次要来介绍的是控制函数的方法。
先前我们须知道函数就是一个特殊形态的物件,他有可有可无的名称属性,还有可以被呼叫的程式属性。
而所有函数都拥有call()、bind()、apply()这些方法。

首先,在person的部分,我们知道this会指向当前的层级的位址,也就是person这个物件,而在logName我们会指向全域物件,发现找不到getFullName这个方法,故会报错。

var person = {    firstname: 'John',    lastname: 'Doe',    getFullName: function() {         var fullname = this.firstname + ' ' + this.lastname;        return fullname;    }}var logName = function(lang1, lang2) {    console.log('Logged: ' + this.getFullName());}logName();

那如果我们可以控制this指向谁不是很好吗?

bind() : Function.prototype.bind(),利用bind来控制this指向谁,可传入物件、函数,他会建立一个新函式并返回。该新函式被呼叫时,会将 this 关键字设为给定的参数Product.bind(color);,color就会是this指向的东西。

所以,我们以logName使用bind方法,去複製拥有getFullName函式的person物件,由于他会回传一个新的函数,所以我们创建一个新的变数logPersonName存取新的函数,并且呼叫他

var person = {    firstname: 'John',    lastname: 'Doe',    getFullName: function() {                var fullname = this.firstname + ' ' + this.lastname;        return fullname;            }}var logName = function(lang1, lang2) {    console.log('Logged: ' + this.getFullName());    console.log('Arguments: ' + lang1 + ' ' + lang2);    console.log('-----------');    }var logPersonName = logName.bind(person);logPersonName('en');Logged: John DoeArguments: en undefined-----------

call() : Function.prototype.call,Product.call(this, name, price);第一个参数是this要指向的东西,而后为我们传入的参数,与bind不同,他并不会创建一个新的函数,call会直接执行,直接决定this指向谁。

可以发现,使用call他会直接执行,并且是可以传入参数的。

var person = {    firstname: 'John',    lastname: 'Doe',    getFullName: function() {            var fullname = this.firstname + ' ' + this.lastname;        return fullname;       }}var logName = function(lang1, lang2) {    console.log('Logged: ' + this.getFullName());    console.log('Arguments: ' + lang1 + ' ' + lang2);    console.log('-----------');}logName.call(person, 'en', 'es');Logged: John DoeArguments: en es-----------

apply() : 与call()所有语法大致上与apply()相同,他们基本上不同处只有 call() 接受一连串的参数,而 apply() 接受单一的array作为参数,如Product.apply(color,['big','slim'])。

很明显跟call是非常相似,差别在于传入的参数型态。

var person = {    firstname: 'John',    lastname: 'Doe',    getFullName: function() {            var fullname = this.firstname + ' ' + this.lastname;        return fullname;       }}var logName = function(lang1, lang2) {    console.log('Logged: ' + this.getFullName());    console.log('Arguments: ' + lang1 + ' ' + lang2);    console.log('-----------');}logName.apply(person, ['en', 'es']);

但我们在实际应用用的到apply吗?

函数借用(function borrowing),可以借用其他物件的方法,如同我们真的有它本身的属性。

也就是我们可以使用其他物件方法,就好像我们本身有它的属性一样。

var person = {    firstname: 'John',    lastname: 'Doe',    getFullName: function() {            var fullname = this.firstname + ' ' + this.lastname;        return fullname;       }}var person2 = {    firstname: 'Jane',    lastname: 'Doe'}console.log(person.getFullName.apply(person2));Jane Doe

function currying,利用bind建立一个新複製的函数,并设定预设参数。

我们所给予的参数,会设定为複製函数的永久参数,multipleByTwo第一个参数设为2,那我们我的a永远就等于2,如同在 multiply函数中return a * b 前面新增var a = 2,而当我们设置两个参数,在呼叫时也传入参数,那么我们呼叫时,传入的参数将会失效,一样是取我们原本设置的两个参数。

function multiply(a, b) {    return a*b;   }var multipleByTwo = multiply.bind(this, 2);console.log(multipleByTwo(4)); // 8var multipleByThree = multiply.bind(this, 3, 2);console.log(multipleByThree(4)); // 6

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章