JS中的call(),apply()和bind()方法

2018-06-14 admin

奔着一星期彻底弄清楚一个javascript小知识点的目的,这次的目标是call apply bind方法

在实际项目中,经常会用到这三个函数,只是简单的知道,都是用来进行上下文绑定的,这三个函数都可以实现,现在看来这三者还是有很大区别的,特别是bind和其他两个的区别

先说call和apply 目的是改变函数的执行上下文,下面列举一些他们的用法

实例一

const zhangsan = {
    name: '张三',
    age: 18    
}

const lisi = {
    name: '李四',
    age: 16
}

function introduce(grade) {
    console.log(`我的名字叫${this.name},我今年${this.age}岁了,上${grade}了`)
}

introduce.call(zhangsan, 3) // 我的名字叫张三,我今年18岁了,上3了
introduce.call(lisi, 4) // 我的名字叫李四,我今年18岁了,上3了
introduce.apply(zhangsan, [3])// 我的名字叫张三,我今年18岁了,上3了
introduce.apply(lisi, [4]) // 我的名字叫李四,我今年18岁了,上3了

实例二

const People = {
    name: '党',
    age: 100,
    introduce: function(grade) {
       console.log(`我的名字叫${this.name},我今年${this.age}岁了,上${grade}了`) 
    }
}

People.introduce('大学') // 我的名字叫党,我今年100岁了,上大学了

const zhangsan = {
    name: '张三',
    age: 18
}

People.introduce.call(zhangsan, 3) // 我的名字叫张三,我今年18岁了,上3了
People.introduce.apply(zhangsan, [3]) // 我的名字叫张三,我今年18岁了,上3了

通过以上两个例子,可以看出,call和apply的区别主要在于传递参数的上的不同,

他们俩的第一个参数都是要执行环境的this, 也就是说执行函数的上下文

第二个参数apply是以数组的方式以此传递, call要一个一个传

需要注意的一点,他们的第二个参数都可以穿arguments

下面就看下bind函数的具体用法

还是老样子,列举一些例子,例子更能直观的感受其用法

还是以上面代码为基础

const wangwu = {
    name: '王五',
    age: 20
}
People.introduce.bind(wangwu, 4)  // ƒ (grade) {
                                  //   console.log(`我的名字叫${this.name},我今年        
                                  //   ${this.age}岁了,上                 
                                  // }
可以看到输出的是一个函数体

所以, bind后函数不会执行, 只是返回一个改变上下文的函数副本, 而call和apply是直接执行的函数

如果想得到和call apply一样的效果,需要手动执行下改函数

People.introduce.bind(wangwu, 4)() // 我的名字叫王五,我今年20岁了,上4了

查了下bind在ie6 ~ ie8下bind的兼容性不好,如果需要兼容ie低版本浏览器的,需要模拟其用法

代码如下

if(!function(){}.bind) {
    Function.prototype.bind = function(context) {
        const self = this
        const args = Array.prototype.slice.call(arguments)
        return function() {
            return self.apply(context, args.slice(1))
        }
    }
}

细想下来,上面这段代码的知识点特别多

clipboard.png

clipboard.png

通过上面两个截图可以很明确的知道需要让this保存调用它的值

  • 需要扩展方法的时候,都需要先判断是否已经存在,如果不存在则会在原型prototype上添加方法
  • 将伪数组转化为真正的数组 Array.protoype.slice.call(arguments) 数组slice的用法,具体怎么使用可以参考这个
  • 返回一个函数,把该函数传递给bind的第一个参数当做执行上下文, 由于args已经是一个数组,排除第一项,之后的参数作为第二部分参数传给apply。

原文链接:https://segmentfault.com/a/1190000015292625

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-34072.html

文章标题:JS中的call(),apply()和bind()方法

相关文章
JavaScript实现PC手机端和嵌入式滑动拼图验证码三种效果
PC和手机端网站滑动拼图验证码效果源码,同时包涵了弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值,嵌入式Demo,使用表单形式提交二次验证所需的验证结果值,移动端手动实现弹出式Demo三种效果 首先要确认前端使用页面,比如...
2017-03-17
React.js编程思想
JavaScript框架层出不穷,在很多程序员看来,React.js是创建大型、快速的Web应用的最好方式。这一款由Facebook出品的JS框架,无论是在Facebook还是在Instagram中,它的表现都非常出色。 使用React.j...
2015-11-12
从2014年的发展来展望JS的未来将会如何
<font face="寰�杞�闆呴粦, Arial, sans-serif ">2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
Vue获取DOM元素样式和样式更改示例
在 vue 中用 document 获取 dom 节点进行节点样式更改的时候有可能会出现 ‘style’ is not definde的错误,这时候可以在 mounted 里用 $refs 来获取样式,并进行更改: <template...
2017-03-13
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: <!DOCTYPE html> <html lang="en"> <head> ...
2017-03-13
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
three.js实现围绕某物体旋转
话不多说,请看代码: 可以拖动右上角观察变化 <!DOCTYPE html> <html lang="en" style="width: 100%; height:100%;"&gt...
2017-02-17
NodeJS参考手册pdf版
下载地址:Nodejs参考手册PDF版下载 ...
2015-11-12
Riot.js:不足1KB的MVP客户端框架
Riot.js是一款MVP(模型-视图-呈现)开源客户端框架,其最大的特点就是体积非常小,不足1KB,虽然体积小,但它可以帮助用户构建大规模的Web应用程序。 Riot.js是由Moot公司开发,目前最新版本为v0.9.2,遵循MIT开源许...
2016-03-11
typeof、instanceof和contructor的区别
typeof:以字符串的形式返回变量的原始类型,typeof在两种情况下会返回"undefined":一个变量没有被声明的时候,和一个变量的值是undefined的时候,注意,typeof null也会返回object,...
2015-11-12
回到顶部