博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js中call、apply、bind那些事
阅读量:5835 次
发布时间:2019-06-18

本文共 2439 字,大约阅读时间需要 8 分钟。

前言

面试,几乎每次都会问到一个js中关于call、apply、bind的问题,比如…

  • 怎么利用call、apply来求一个数组中最大或者最小值

  • 如何利用call、apply来做继承

  • apply、call、bind的区别和主要应用场景

作用

首先问个问题,这三个函数的存在意义是什么?答案是改变函数执行时的上下文,再具体一点就是改变函数运行时的this指向。

举个栗子
function Person(name) {    this.name = name}Person.prototype = {    constructor: Person,    showName: function() {        console.log(this.name)    }}var person = new Person('shifeng')person.showName() // 输入'shifeng'
接下来
var animal = {    name: 'cat}

上面代码中有一个对象字面量,他没有所谓的showName方法,但是我还是想用?怎么办?(坑爹了,这好像在让巧媳妇去做无米之炊),不过没关系,call、apply、bind可以帮我们干这件事。

// 以下三种都会输出'cat'// 1. callperson.showName.call(animal)// 2. applyperson.showName.apply(animal)// 3. bindperson.showName.bind(animal)

我们拿别人的showName方法,并动态改变其上下文帮自己输出了信息,说到底就是实现了复用

区别

上面看起来三个函数的作用差不多,干的事几乎是一样的,那为什么要存在3个家伙呢,留一个不就可以。所以其实他们干的事从本质上讲都是一样的动态的改变this上下文,但是多少还是有一些差别的...

call, apply与bind的差别

call和apply改变了函数的this上下文后便执行该函数, 而bind则是返回改变了上下文的一个函数

call和apply的区别

他们俩之间的差别在于参数的区别,call和aplly的第一个参数都是要改变上下文的对象,而call从第二个参数开始以参数列表的形式展现,apply则是把除了改变上下文对象的参数放在一个数组里面作为它的第二个参数。

fn.call(contextObj, arg1, arg2, arg3...)fn.apply(contextObj, [arg1, arg2, aeg3...])

应用场景

  • 求数组中的最大值和最小值(并不是最佳选择)

var arr = [34,5,3,6,54,6,-67,5,7,6,-8,687]// max、min 是 Math 中的静态方法,因此必然是没有使用上下文的必要的。// 因此 call、apply 绑定只需要用 null 或者 undefined 占位就可以了。Math.max.call(null, 34,5,3,6,54,6,-67,5,7,6,-8,687) // 同Math.max(34,5,3,6,54,6,-67,5,7,6,-8,687)Math.max.apply(null, arr)Math.min.call(undefined, 34,5,3,6,54,6,-67,5,7,6,-8,687)Math.min.apply(undefined, arr)// 最佳方法, ES6数组解构Math.max(...arr)Math.min(...arr)
  • 将伪数组转化为数组

js中的伪数组(例如通过document.getElementsByTagName或者document.querySelectorAll获取的元素)具有length属性,并且可以通过0、1、2…下标来访问其中的元素,但是没有Array中的push、pop等方法。我们可以利用call、apply来将其转化为真正的数组这样便可以方便地使用数组方法了。

var arrayLike = {    0: 'shifeng',    1: 'xingyun',    2: 'ruxue',    length: 3}

上面就是一个普通的对象字面量,怎么把它变成一个数组呢?最简单的方法就是

var arr = Array.prototype.slice.call(arrayLike)

上面arr便是一个包含arrayLike元素的真正的数组啦(注意数据结构必须是以数字为下标而且一定要有length属性)

  • 数组追加

在js中要往数组中添加元素, 可以直接用push方法

var arr1 = [1,2,3]var arr2 = [4,5,6]// Array.prototype.push.apply(arr1, arr2)[].push.apply(arr1, arr2)// 使用一个辅助的空数组(为了访问非静态方法),就是把arr2利用apply的数组参数特性push到arr1中.// 这样通过解构可以写成 arr1.push(...arr2), 如果需要返回一个全新的对象,还可以使用 [...arr1, ...arr2]。// 还可以写成var newArr =  arr1.concat(arr2)// arr1 [1, 2, 3, 4, 5, 6]// arr2 [4,5,6]
  • 判断变量类型

对于对象型的数据类型, 我们可以借助call来得知他的具体类型, 例如数组

function isArray(obj){  return Object.prototype.toString.call(obj) == '[object Array]';}isArray([]) // trueisArray('qianlong') // false

转载地址:http://rbycx.baihongyu.com/

你可能感兴趣的文章
java只能的round,ceil,floor方法的使用
查看>>
新开的博客,为自己祝贺一下
查看>>
采用JXL包进行EXCEL数据写入操作
查看>>
将txt文件转化为json进行操作
查看>>
线性表4 - 数据结构和算法09
查看>>
我的2014-相对奢侈的生活
查看>>
Java设计模式
查看>>
Spring Cloud 微服务分布式链路跟踪 Sleuth 与 Zipkin
查看>>
ORM数据库框架 SQLite 常用数据库框架比较 MD
查看>>
华为OJ 名字美丽度
查看>>
微信公众号与APP微信第三方登录账号打通
查看>>
Windows 下最佳的 C++ 开发的 IDE 是什么?
查看>>
软件工程师成长为架构师必备的十项技能
查看>>
python 异常
查看>>
百度账号注销
查看>>
mysql-This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME 错误解决
查看>>
BIEE Demo(RPD创建 + 分析 +仪表盘 )
查看>>
Cocos2dx 3.0开发环境的搭建--Eclipse建立在Android工程
查看>>
基本概念复习
查看>>
重构第10天:提取方法(Extract Method)
查看>>