JavaScript中的bind,call和apply函数的用法和区别
一直没怎么使用过JavaScript中的bind,call和apply, 今天看到一篇比较好的文章,觉得讲的比较透彻,所以记录和总结如下
首先要理解的第一个概念,JavaScript中函数调用的方式,总结下来,有以下4种
1. 方法调用
2. 正常函数调用
3. 构造器函数调用
4. apply/call 调用
要明白的第2个概念, JavaScript 中的函数,无论是上面哪种函数调用方式,除了你函数声明时定义的形参外,还会自动给函数添加两个形参,分别是this 和 arguments
要明白的第3个概念, Javascript中的函数,存在函数上下文(context) 这么一个概念, 而函数上下文又存在【定义时上下文】,【运行时上下文】,【上下文是可以改变的】这样子的情况, 而第2个概念中的this, 指向的就是当前函数中的上下文
要明白的第4个概念, 也是我们今天在这里要讲的call, apply函数的目的 => 它们在JavaScript函数中存在的目的,就是为了改变某个函数运行时的上下文(context)而存在的, 换句话说,是为了改变函数体内部this的指向
现在我们一个一个来看
1. 方法调用函数的方式
应该可以理解,所谓方法调用函数的方式,就是说把一个函数定义为一个对象的方法,然后通过调用这个对象的该方法,来达到调用该函数的目的
直接上代码
var myValue = {
para: 5,
setFunc: function(xvalue){
this.para = xvalue;
}
}
myValue.setFunc(0);
在这里,函数setFunc作为变量myValue的也给方法存在,所以使用myValue.setFunc()的形式就可以调用它。在这里,函数setFunc中的this,绑定的上下文就是myValue, 所以this.para取到的就是对象myValue的para属性
2. 正常函数调用
function setValue(xvalue)
{
this.para = xvalue;
} setValue(5);
上面,我们正常的定义了一个函数setValue,然后正常的调用setValue(5). 在这里,函数setValue里面的this绑定的是全局对象. 如果这段JavaScript代码是运行在浏览器中,那么这里的this指向的就是浏览器的全局对象window. 所以这里this.para 等价于 window.para. 那有人肯定会很奇怪,如果当前浏览器的window中不存在para属性呢,那么这个时候,在这里,javascript会自动给全局对象window加上para属性,同时在这里赋值为5
3. 构造器函数调用
JavaScript 中的构造函数,大家知道,首先作为构造函数的函数名首字母需要大写,在函数内部必须有this关键字。 我们来看一下构造函数的调用
function SetValue(xvalue)
{
this.para = xvalue;
} var myFunc = new SetValue(5);
在这里,SetValue函数不是一个普通函数,它是一个构造函数, 调用它是使用new 关键字来生成一个新的对象myFunc, 在这里,this绑定的上下文就不再是window对象了,而是新的对象myFunc
所以 console.log(myFunc.para) // 输出5
4. apply/call 来调用函数
我们可以看到,上面三种函数调用方式,this指向都不一样,但是我们程序员都无法自定义或者说更改this的绑定指向。 那么,如果我们需要在程序中自己指定this的绑定上下文,有没用方法呢。这就是apply/call的用处了
JavaScript 中所有函数都有一个公共的prototype => Function, 而Function 这个原型自带了不少的属性和方法,其中就有apply, call, bind方法。 我们首先来看看apply 和 call方法
apply => 当一个对象没有某个方法时,但这个方法在其他地方存在。可能使用这个方法的apply方法,把这个方法运用到这个对象上。 它有两个参数 apply(thisObj, [arg1,arg2,arg3...])
第1个参数是传递给这个函数用来绑定this的值(指定这里this所绑定的上下文是哪一个)
第2个参数是一个数组
我们直接上代码,来看一个例子
function setValue(xvalue)
{
this.para = xvalue;
} var applyObj = {}; setValue.apply(applyObj,[10]); alert(setValue.para); // undefined
alert(applyObj.para); //
可以看到,刚开始对象applyObj是我们定义的一个空对象,然后通过函数原型默认持有的apply方法,我们把函数setValue通过apply方法应用到空对象applyObj上去,使得对象applyObj拥有了setValue方法,同时,通过第一个参数,指定this所绑定的当前上下文是applyObj对象,传入的参数为10
call 方法和apply方法几乎没有区别,唯一的区别是, 它的第二个参数不是以数组的形式,而是通过逗号来列出参数的形式 call(thisObj,arg1,arg2,arg3...) 我们直接来看代码
function addValue(xvalue, yvalue)
{
this.para = xvalue + yvalue;
} var applyObj = {}; addValue.call(applyObj,2,3); alert(addValue.para); // undefined
alert(applyObj.para); //
当然, 如果在call 或者apply方法中,你传入的第一个参数是null, 那么在这种情况下,函数中的this 指向的依然会是全局对象window
然后,我们来看一看bind
bind的功能和上面一样,它接受的参数和call一样. 唯一的区别是,函数使用bind方法后会生成一个新的函数,你想什么时候调用新的函数,就什么时候调用. 我们来看一个例子
var myObj = {
"x" : 4
};
function addValue(y) {
alert(this.x + y);
}
addValue.apply(myObj, [5]);
addValue.call(myObj, 5);
var foo1 = addValue.bind(myObj, 5);
foo1();
JavaScript中的bind,call和apply函数的用法和区别的更多相关文章
- SQL 中详解round(),floor(),ceiling()函数的用法和区别?
SQL 中详解round(),floor(),ceiling()函数的用法和区别? 原创 2013年06月09日 14:00:21 摘自:http://blog.csdn.net/yueliang ...
- sql中详解round(),floor(),ceiling()函数的用法和区别?
round() 遵循四舍五入把原值转化为指定小数位数,如:round(1.45,0) = 1;round(1.55,0)=2floor()向下舍入为指定小数位数 如:floor(1.45,0)= 1; ...
- Javascript中的bind()函数
今天看到公司大神的一段代码: function ReplaceProcessor() { this._dom = { btnReplace: $('#ro_btnReplace'), btnCompl ...
- javascript 中的 bind (编辑中。。。。)
这篇文章说的非常好!http://my.oschina.net/blogshi/blog/265415 我的体会就是,函数中的this,指的是运行时,它是被哪个对象调用的.因为javascrpit的函 ...
- 把玩Javascript中的bind
前言 今天闲着无聊随便逛了逛MDN,忽而看到一个方法Function.prototype.bind(),突然发现除了使用这个方法之外都没有仔细琢磨过这个方法.于是乎,找到了kill time的事情-写 ...
- Javascript中的bind详解
前言 用过React的同学都知道,经常会使用bind来绑定this. import React, { Component } from 'react'; class TodoItem extends ...
- JavaScript中的bind方法及其常见应用
一.bind()方法的实现 在JavaScript中,方法往往涉及到上下文,也就是this,因此往往不能直接引用.就拿最常见的console.log("info…")来说,避免书写 ...
- 理解JavaScript中的arguments,callee,caller,apply
arguments 该对象代表正在执行的函数和调用它的函数的参数. [function.]arguments[n] 参数function :选项.当前正在执行的 Function 对象的名字. n : ...
- [转] 理解 JavaScript 中的 Array.prototype.slice.apply(arguments)
假如你是一个 JavaScript 开发者,你可能见到过 Array.prototype.slice.apply(arguments) 这样的用法,然后你会问,这么写是什么意思呢? 这个语法其实不难理 ...
随机推荐
- java-消息队列相关-activeMQ
,1,如何防止activeMQ崩溃导致消息丢失呢? 第一点,首先消息需要使用持久化消息,服务挂掉,重启服务后消息依然可以消费,不会丢失: 第二点,ActiveMQ采用主从模式搭建集群,比如搭建3台主从 ...
- Hadoop-No.3之序列化存储格式
序列化存储指的是将数据结构转化为字节流的过程,一般用于数据存储或者网络传输.与之相反, 反序列化是将字节流转化为数据结果的过程.序列化是分布处理系统(比如Hadoop)的核心,原因在于他能对数据进行转 ...
- 课程 6;比特币产生,分配(2100w,10个矿区)
www.8btc.com (每21w个,减半分配)
- include和require的区别(PHP版本7)
亲自测试了一下,发现include有条件包含require无条件包含这个区别在PHP7版本中(据说PHP5以后)是不存在的了,也就是在if(false){ } 中都不会执行:还有一个返回值的问题,测试 ...
- UI案例
<Window x:Class="WpfDemo2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/20 ...
- vim文本编辑器的用法
vi是一个命令行界面的文本编辑器: vim是vi的改进版: vim不仅有文本编辑:还有文本处理.代码编辑等功能: 1.VIM简介 vim 命令可启动vim编辑器: 一般 vim 文件路径 来使用: ...
- java+批量下载大文件
我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...
- 计算机HDMI端口与电视机相连
造冰箱的大熊猫@cnblogs 2019/2/27 打算通过HDMI接口将计算机桌面投影到电视机上,结果遇到问题,折腾了好一阵才搞定.现将这些问题记录下来 1.设备环境 计算机:使用Ubuntu 1 ...
- LibreOffice/Calc:单元格设置下拉菜单
造冰箱的大熊猫,本文适用于LibreOffice Calc 5.1.6.2 + Ubuntu 16.04@cnblogs 2019/1/2 LibreOffice是一个类似Microsoft Off ...
- 洛谷P3193 GT考试 kmp+矩阵优化dp
题意 求\(N\)位数字序列(可以有前导0)中不出现某\(M\)位子串的个数,模\(K\). \(N<=10^9,M<=20,K<=1000\) 分析 设\(dp[i][j]\)表示 ...