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

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

JS中的call、apply、bind都是用来改变函数中this指向的

box.onclick = function(){    var name = 1;  function fn(){    alert(this.name);  }  fn();      console.log(this.name);};

alert出来的this.name 会显示undefined

console.log显示出来的this.name为1

问题来了,函数里边的函数的this不是外层函数的this,而是window。

一般我们解决这个问题会用

var _this = this;

来保存外层函数的this在内层函数中使用。

但本文将介绍一种更加常用的方法改变this指向。

box.onclick = function(){  function fn(){     console.log(this);   }   fn.call(this); };

很神奇吧,call的作用就是改变this的指向的,第一个传的是一个对象,就是你要借用的那个对象。

fn.call(this); 

  这里的意思是让this去调用fn这个函数,这里的this是box,这个没有意见吧?如果这个你不清楚,很可能你是javscript的新朋友。box调用fn,这句话非常重要,我们知道this它始终指向一个对象,刚好box就是一个对象。那么fn里面的this就是box。

box.onclick = function(){  function fn(){     console.log(this);   }   fn.call(this); };

这句话在某些情况下是可以简写的,比如:

box.onclick = function(){  var fn = function(){     console.log(this); //box   }.call(this); };

或者这样:

box.onclick = function(){  (function(){     console.log(this);   }.call(this)); //box };

又或者这样:

var objName = {name:'JS2016'};var obj = {  name:'0 _ 0',   sayHello:function(){     console.log(this.name);   }.bind(objName) }; obj.sayHello();//JS2016

call和apply、bind都是用来改变this的指向的,但也有一些小小的差别。下面我们来看看它们的差别在哪:

function fn(a,b,c,d){  console.log(a,b,c,d);}//call fn.call(null,1,2,3); //apply fn.apply(null,[1,2,3]); //bind var f = fn.bind(null,1,2,3); f(4); 结果如下: 1 2 3 undefined 1 2 3 undefined 1 2 3 4

  前面说过第一个参数传的是一个你要借用的对象,但这么我们不需要,所有就传了一个null,当然你也可以传其他的,反正在这里没有用到,除了第一个参数后面的参数将作为实际参数传入到函数中。

  call就是挨个传值,apply传一个数组,bind也是挨个传值,但和call和apply还有一些不同,使用call和apply会直接执行这个函数,而bind并不直接执行,而是将绑定好的this重新返回一个新函数,什么时候调用由你自己决定。

var objName = {name:'JS2016'};var obj = {  name:'0 _ 0',   sayHello:function(){     console.log(this.name);   }.bind(objName) }; obj.sayHello();//JS2016

这里也就是为什么我要用bind的原因,如果用call的话就会报错了。自己想想这个sayHello在obj都已经执行完了,就根本没有sayHello这个函数了。

这几个方法使用的好的话可以帮你解决不少问题比如: 

正常情况下Math.max只能这样用

Math.max(10,6)

但如果你想传一个数组的话你可以用apply

var arr = [1,2,30,4,5]; console.log(Math.max.apply(null,arr));

  又或者你想让伪数组调用数组的方法

function fn(){  [].push.call(arguments,3);  console.log(arguments); //[1, 2, 3] } fn(1,2);

再者:

var arr = ['aaabc'];console.log(''.indexOf.call(arr,'b')); //3

实际上浏览器内部根本就不在乎你是谁,它只关心你传给我的是不是我能够运行的,如下: 

正常情况

var str = 'aaabc';console.log(str.indexOf('b'));

而这种情况其实做的事情和上面模一样,看我来拆解。

var arr = ['aaabc'];''.indexOf.call(arr);

这句话就是说让arr调用字符串的indexOf方法,前面说过了浏览器内部不在乎你是谁,所以谁都可以来调用,但不是100%成功,具体看如下。

''.indexOf.call(arr,'b')

这里的arr就是[‘aaabc’],内部很可能拆成了’aaabc’,因此就成了下面的这段代码。

'aaabc'.indexOf('b');

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

你可能感兴趣的文章
关于程序的单元测试
查看>>
mysql内存优化
查看>>
都市求生日记第一篇
查看>>
Java集合---HashMap源码剖析
查看>>
SQL优化技巧
查看>>
thead 固定,tbody 超出滚动(附带改变滚动条样式)
查看>>
Dijkstra算法
查看>>
css 动画 和 响应式布局和兼容性
查看>>
csrf 跨站请求伪造相关以及django的中间件
查看>>
MySQL数据类型--与MySQL零距离接触2-11MySQL自动编号
查看>>
生日小助手源码运行的步骤
查看>>
Configuration python CGI in XAMPP in win-7
查看>>
bzoj 5006(洛谷 4547) [THUWC2017]Bipartite 随机二分图——期望DP
查看>>
CF 888E Maximum Subsequence——折半搜索
查看>>
欧几里德算法(辗转相除法)
查看>>
面试题1-----SVM和LR的异同
查看>>
MFC控件的SubclassDlgItem
查看>>
如何避免历史回退到登录页面
查看>>
《图解HTTP》1~53Page Web网络基础 HTTP协议 HTTP报文内的HTTP信息
查看>>
unix环境高级编程-高级IO(2)
查看>>