call(),apply(),bind()
函数你们可能都有所了解,可是在平时搬砖过程当中极可能或者基本没用过,学过但都淡忘了。前端
可是在大量第三方的框架(库),甚至js本身都在 源码中大量使用 call,apply
函数。因此今天和你们仔细讨论下它们在 开发中的应用场景 。jquery
this
。函数对象
的方法,也就是说只有函数才能够直接调用这些方法。ps:call,apply,bing属于this显示绑定,还有好几种其余的this绑定方式,感兴趣的能够点这里。程序员
this
。call
: 能够有n个参数,从第二个参数开始的全部参数都是原函数的参数。数组
`apply`:只有两个参数,而且第二个参数必须为数组,数组中的全部元素一一对应原函数的参数。 `bind`: 只有一个参数,即要绑定的this。
call 语法: foo.call(this, arg1,arg2, ... ,argn ); apply 语法: foo.apply(this, [ arg1,arg2, ... ,argn ] ); bind 语法: foo.bind(this);
call,apply
: 调用后当即执行原函数。安全
`bind`: 调用后返回已经绑定好this的函数。
小例子一枚:app
function foo(a,b){ console.log(a+b); } foo.call(null,'海洋','饼干'); // 海洋饼干 这里this指向不重要就写null了 foo.apply(null, ['海洋','饼干'] ); // 海洋饼干 var fun = foo.bind(null); fun('海洋','饼干'); // 海洋饼干
这是咱们今天讨论的主题,这三个函数如何应用?什么状况下使用?能改变this
指向又能咋滴?框架
先考虑一个问题,若是你使用var arr = document.getElementsByTagName('li')
获取了5个li
元素,你如今须要获取其中的第2,3,4三个元素,你会怎么作?函数
这样arr.slice(1,4);
? 啊哦,TypeError -- arr.slice is not a function(slice不是函数)
,数组操做在平常搬砖中很是常见,我见过最傻的解决这个问题的方式是使用循环,将须要的元素一个个添加到一个新数组里0.0,下面我介绍的方法彻底能够在实战中使用,能够给你的代码加分哦,很是方便简洁(中高级前端程序员中,算是基本操做了)。优化
先要介绍一个概念( 伪数组 ),这也是为何咱们刚刚slice切割数组时出错的缘由: (对新手来讲算是干货了,知道的能够跳过)this
什么是伪数组?( 字面的意思已经呼之欲出了 )
push()、slice()
等方法简单来讲就是能够像数组同样操做的对象,可是没有数组的方法。
js中存在大量伪数组,如 :
1. function的arguments对象。 2. getElementsByName(),getElementsByTagName(),childNodes/children 等方法的返回值。 3. 还有比较常见的jquery,使用它获取的元素也是伪数组。
回到原来的问题,如何截取伪数组中的元素:伪数组没有这些方法,咱们'借用'Array的slice不就好了
[].slice.call(arr,1,4); // 推荐写法
不想借用你能够直接给伪数组添加一个slice函数,如
arr.slice = [].slice; arr.slice(1,4);
固然,'借用' 更方便,直接添加会致使伪数组对象'污染'。
若是能够随意改变原对象,能够 直接将其转成真正的数组对象。
[].slice.call(arr);
继承方式多种多样,咱们如今讨论的这种是其中很重要的一种实现方式,用call
实现 js 构造函数继承 。
function person(name){ this.name = name } function man(name){ this.age = '男'; person.call(this,name); // 继承 man } var me = new man('海洋饼干'); console.log(me.name,me.age); // '海洋饼干' '男'
function person(name){ this.name = name } function man(name){ this.age = '男'; } function manProgrammer(name){ this.girlfriend = null; person.call(this,name); // 继承 person man.call(this,name); // 继承 man } var me = new manProgrammer('海洋饼干'); console.log(me.name,me.age,me.girlfriend); // '海洋饼干' '男' null
将一个对象强制且永久性绑定到函数的this上,使用call,apply或者其余的绑定方式都没法改变(除了new绑定,固然,能够手动撸一个new都没法改变的硬绑定)
直接看例子:
var fun ; var obj = { a : 1, foo : function(){ var _this = this; //平时有没有过这种写法? 为了防止this指向问题 //将this赋值给一个变量,间接维持了this的安全性 fun = function(){ console.log(_this.a); } } } obj.foo(); fun(); // 1 var obj1 = { a : 2} obj.foo.call(obj1); // 直接修改_this所绑定的值,boom了 fun(); // 2
可是这种方法感受上是在逃避问题,直接不使用this了 ? 这真的不是什么好的解决问题的态度。下面使用咱们的bind来优化一下:
var fun ; var obj = { a : 1, foo : function(){ // 不使用 _this, 避免无谓的变量声明 fun = function(){ console.log(this.a); }.bind(this); // 代码很简洁,很漂亮(b格) } } var obj1 = { a : 2} obj.foo(); fun(); // 1 fun.call(obj1); // 1 call ,apply等绑定 没法修改 // 这里和上面call的位置不一样是由于this所处于不一样的位置
这样替代 _this
很规(zhuang)范(b)呢
ps:call,apply,bing属于this显示绑定,还有好几种其余的this绑定方式,感兴趣的能够点这里。
Math.max和min方法,接收多个参数,比较出极值,这里用到apply的一个默认功能:展开数组,传入一个数组参数就能够默认将这个数组转成一个个参数的形式赋给原函数
var num = [6,9,-3,-5]; console.log(Math.max.apply(Math,num)); // 9 等价 console.log(Math.max(6,9,-3,-5)); console.log(Math.min.apply(Math,num)); // -5 等价 console.log(Math.min(6,9,-3,-5));
合并数组常见有三种方式,1.循环 2.Array的concat() 3. 使用apply()合并
这里是使用最简便的apply
var a = [1,2,3]; var b = [4,5,6]; [].push.apply(a,b); // 借用数组的push方法 等价 a.push(4,5,6); console.log(a); // [1, 2, 3, 4, 5, 6]
以为对你有帮助点个赞呗555
你们有什么实用点的黑科技欢迎私信评论 分享,我会贴上id和你的分享 >_<