bind、call、apply函数的用法

js 里函数调用有 4 种模式:方法调用正常函数调用构造器函数调用apply/call 调用
同时,无论哪种函数调用除了你声明时定义的形参外,还会自动添加 2 个形参,分别是 this 和arguments
arguments 不涉及到上述 3 个函数,所以这里只谈 thisthis 的值,在上面 4 中调用模式下,分别会绑定不同的值。分别来说一说:
方法调用
这个很好理解,函数是一个对象的属性,比如

var a = {
    v : 0,
    f : function(xx) {
        this.v = xx;
    }
}
a.f(5);

这个时候,上面函数里的 this 就绑定的是这个对象 a。所以 this.v 可以取到对象 a 的属性 v

正常函数调用:
依然看代码

function f(xx) {
    this.x = xx;
}
f(5);

这个时候,函数 f 里的 this 绑定的是全局对象,如果是在浏览器运行的解释器中,一般来说是 window 对象。所以这里 this.x 访问的其实是 window.x ,当然,如果 window 没有 x 属性,那么你这么一写,按照 js 的坑爹语法,就是给 window 对象添加了一个 x 属性,同时赋值。

构造器函数调用
构造函数一直是我认为是 js 里最坑爹的部分,因为它和 js 最初设计的基于原型的面向对象实现方式格格不入,就好像是特意为了迎合大家已经被其他基于类的面相对象实现给惯坏了的习惯。
如果你在一个函数前面带上 new 关键字来调用,那么 js 会创建一个 prototype 属性是此函数的一个新对象,同时在调用这个函数的时候,把 this 绑定到这个新对象上。当然 new 关键字也会改变return 语句的行为,不过这里就不谈了。看代码

function a(xx) {
    this.m = xx;
}
var b = new a(5);

上面这个函数和正常调用的函数写法上没什么区别,只不过在调用的时候函数名前面加了关键字 new罢了,这么一来,this 绑定的就不再是前面讲到的全局对象了,而是这里说的创建的新对象,所以说这种方式其实很危险,因为光看函数,你不会知道这个函数到底是准备拿来当构造函数用的,还是一般函数用的。所以我们可以看到,在 jslint 里,它会要求你写的所有构造函数,也就是一旦它发现你用了 new 关键字,那么后面那个函数的首字母必须大写,这样通过函数首字母大写的方式来区分,我个人只有一个看法:坑爹:)

apply/call 调用:
我们知道,在 js 里,函数其实也是一个对象,那么函数自然也可以拥有它自己的方法,有点绕,在js 里,每个函数都有一个公共的 prototype —— Function,而这个原型自带有好几个属性和方法,其中就有这里困惑的 bindcallapply 方法。先说 apply 方法,它让我们构造一个参数数组传递给函数,同时可以自己来设置 this 的值,这就是它最强大的地方,上面的 3 种函数调用方式,你可以看到,this 都是自动绑定的,没办法由你来设,当你想设的时候,就可以用 apply()了。apply 函数接收 2 个参数,第一个是传递给这个函数用来绑定 this 的值,第二个是一个参数数组。看代码

function a(xx) {
    this.b = xx;
}
var o = {};
a.apply(o, [5]);
alert(a.b);    // undefined
alert(o.b);    // 5

是不是很神奇,函数 a 居然可以给 o 加属性值。当然,如果你 apply 的第一个参数传递 null,那么在函数 a 里面 this 指针依然会绑定全局对象。

call() 方法和 apply() 方法很类似,它们的存在都是为了改变 this 的绑定,那 call() 和apply() 有什么区别呢?就我个人看来,没啥鸟区别。。。开玩笑!刚刚说了,上面 apply() 接收两个参数,第一个是绑定 this 的值,第二个是一个参数数组,注意它是一个数组,你想传递给这个函数的所有参数都放在数组里,然后 apply() 函数会在调用函数时自动帮你把数组展开。而 call()呢,它的第一个参数也是绑定给 this 的值,但是后面接受的是不定参数,而不再是一个数组,也就是说你可以像平时给函数传参那样把这些参数一个一个传递。所以如果一定要说有什么区别的话,看起来是这样的

function a(xx, yy) {
    alert(xx, yy);
    alert(this);
    alert(arguments);
}
a.apply(null, [5, 55]);
a.call(null, 5, 55);

仅此而已。

最后再来说 bind() 函数,上面讲的无论是 call() 也好, apply() 也好,都是立马就调用了对应的函数,而 bind() 不会, bind() 会生成一个新的函数,bind() 函数的参数跟 call() 一致,第一个参数也是绑定 this 的值,后面接受传递给函数的不定参数。 bind() 生成的新函数返回后,你想什么时候调就什么时候调,看下代码就明白了

var m = {
    "x" : 1
};
function foo(y) {
    alert(this.x + y);
}
foo.apply(m, [5]);
foo.call(m, 5);
var foo1 = foo.bind(m, 5);
foo1();

末了来个吐槽,你在 js 里想定义一个函数,于是你会这么写:

function jam() {};

其实这是 js 里的一种语法糖,它等价于:

var jam = function() {};

然后你想执行这个函数,脑洞大开的你会这么写:

function jam() {}();

但是这么写就报错了,其实这种写法也不算错,因为它确实是 js 支持的函数表达式,但是同时 js 又规定以function 开头的语句被认为是函数语句,而函数语句后面是肯定不会带 () 的,所以才报错,于是聪明的人想出来,加上一对括号就可以了。于是就变成了这样:

(function jam() {}());

这样就定义了一个函数同时也执行它

时间: 2024-10-12 21:27:20

bind、call、apply函数的用法的相关文章

js中bind、call、apply函数的用法

最近一直在用 js 写游戏服务器,我也接触 js 时间不长,大学的时候用 js 做过一个 H3C 的 web 的项目,然后在腾讯实习的时候用 js 写过一些奇怪的程序,自己也用 js 写过几个的网站.但真正大规模的使用 js 这还是第一次.我也是初生牛犊不怕虎,这次服务器居然抛弃 C++ 和 lua 的正统搭配,而尝试用 nodejs 来写游戏服务器,折腾的自己要死要活的我也是醉了. 在给我们项目组的其他程序介绍 js 的时候,我准备了很多的内容,但看起来效果不大,果然光讲还是不行的,必须动手.

js中bind、call、apply函数的用法 (转载)

最近看了一篇不错的有关js的文章,转载过来收藏先!!! 最近一直在用 js 写游戏服务器,我也接触 js 时间不长,大学的时候用 js 做过一个 H3C 的 web 的项目,然后在腾讯实习的时候用 js 写过一些奇怪的程序,自己也用 js 写过几个的网站.但真正大规模的使用 js 这还是第一次.我也是初生牛犊不怕虎,这次服务器居然抛弃 C++ 和 lua 的正统搭配,而尝试用 nodejs 来写游戏服务器,折腾的自己要死要活的我也是醉了. 在给我们项目组的其他程序介绍 js 的时候,我准备了很多

apply() 函数家族介绍

apply() 函数算是R语言中很基础的一个函数,同时还有 sapply()  lapply()  tapply() 函数精简了 apply() 函数的用法. apply() 函数是一个很R语言的函数,可以起到很好的替代冗余的for循环的作用,R语言中的循环操作for和while都是基于R语言本身来实现的,而向量操作是基于底层的C语言函数实现的,所以使用apply()函数家族进行向量计算时高性价比的. apply() 函数可以面向数据框.列表.向量等,同时任何函数都可以传递给 apply() 函

JavaScript中bind、call、apply函数用法详解

在给我们项目组的其他程序介绍 js 的时候,我准备了很多的内容,但看起来效果不大,果然光讲还是不行的,必须动手.前几天有人问我关于代码里 call() 函数的用法,我让他去看书,这里推荐用js 写服务器的程序猿看<javascript编程精粹> 这本书,crockford大神果然不是盖的.之后我在segmentfault上又看到了类似的问题,那边解答之后干脆这里记一笔. 首先,关于 js 定义类或对象的方法,请参看w3school 的这里的这里,写的非常详细和清晰,我不再赘言了. 为了介绍 b

面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗

一.前言    不知道大家还记不记得前几篇的文章:<面试官:能解释一下javascript中的this吗> 那今天这篇文章虽然是介绍javascript中bind.apply和call函数,但是多少也和this有点关联. 假如在前面那场面试末尾,面试官不依不饶继续问你javascript中的this,那看完本篇文章后一定还会有收获. (本篇文章不会站在this的角度去回答问题,而是重于解释bind.apply和call这三个函数的用法和使用场景) 二.正戏开始 面试官:能解释一下javascr

Javascript中bind、call、apply函数用法

js 里函数调用有 4 种模式:方法调用.正常函数调用.构造器函数调用.apply/call 调用. 同时,无论哪种函数调用除了你声明时定义的形参外,还会自动添加 2 个形参,分别是 this 和arguments. arguments 不涉及到上述 3 个函数,所以这里只谈 this.this 的值,在上面 4 中调用模式下,分别会绑定不同的值.分别来说一说: 方法调用: 这个很好理解,函数是一个对象的属性,比如 var a = { v : 0, f : function(xx) { this

关于call和apply函数的区别及用法

call和apply函数是function函数的基本属性,都可以用于更改函数对象和传递参数,是前端工程师常用的函数.具体使用方法请参考以下案列: 例如: 申明函数: var fn = function (msg, isalert) { if (isalert) alert(this + msg); }; 用法: call: fn.call(/*context,arg1,arg2,...*/); apply:fn.call(/*context,[arg1,arg2,...]*/); 讲述:第一个参

JavaScript中的bind,call和apply函数的用法和区别

一直没怎么使用过JavaScript中的bind,call和apply, 今天看到一篇比较好的文章,觉得讲的比较透彻,所以记录和总结如下 首先要理解的第一个概念,JavaScript中函数调用的方式,总结下来,有以下4种 1. 方法调用 2. 正常函数调用 3. 构造器函数调用 4. apply/call 调用 要明白的第2个概念, JavaScript 中的函数,无论是上面哪种函数调用方式,除了你函数声明时定义的形参外,还会自动给函数添加两个形参,分别是this 和 arguments 要明白

R语言apply()函数用法

在R语言的帮助文档里,apply函数的功能是: Retruns a vector or array or list of values obtained by applying a function to margins of an array or matrix. 就是说apply把一个function作用到array或者matrix的margins(可以理解为数组的每一行或者每一列)中,返回值时vector.array.list. 简单的说,apply函数经常用来计算矩阵中行或列的均值.和值