博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
apply, bind, call--绑定this的方法
阅读量:5270 次
发布时间:2019-06-14

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

Function.prototype.call(),Function.prototype.apply(),Function.prototype.bind()

是三种改变函数内部this指向(即函数执行时所在作用域)的方法。

 

1.Function.prototype.call(thisValue, param1, param2,....)

1)第一个参数

第一个参数必须是对象,

  • 如果是 空,undefine, null 都默认绑定到window;
  • 如果是基础类型(如字符型,数值型,布尔型)会自动将基础类型转为包装类型,如: Number(5)
  • 如果是this, 表示绑定的是当前作用域
var n = 123;var obj = {    n: 456}function a() {    return this;}// this === windowa.call(); // windowa.call(null); // windowa.call(undefine); //windowa.call(window); // window// this === obja.call(obj); // obj// this === 包装对象a.call(5); // Number(5) {[[PrimitiveValue]]: 5}

2) 其余的参数

其余的参数作为函数调用时传入的参数

function add(a,b) {  return a + b;}//this表示固定当前this的指向; this === windowadd.call(this, 1, 2); // 3

3)应用

// 调用对象的原生方法var obj = {  a: 5}console.log(obj.hasOwnProperty('toString')); // fasleobj.hasOwnProperty = function() { // 覆盖obj对象继承自原型链上的方法  return true; // 改变的是obj本身的方法,原型链上的方法不变}console.log(obj.hasOwnProperty('toString')); // true// obj可以使用原型链上的方法,表示在obj的作用域使用hasOwnProperty的方法console.log(Object.prototype.hasOwnProperty.call(obj)); // false

2. Function.prototype.apply(thisValue, [param1, ....])

1)第一个参数和call方法规则相同

2)第二个参数

第二个参数是数组, 将数组中的参数依次作为调用函数的参数

function add(a,b) {  return a + b;}add.apply(this, [1, 2])

3)应用

//1) 查找数组的最大值const arr = [1,3,5];Math.max.apply(null, arr); // 5// 还可以Math.max(...arr); // 5// 2) 将数组的空项转为undefined;undefine可以被遍历,空会被遍历函数忽略const arr = [1,,4];Array.apply(null, arr); // [1,undefined,4] Array是数组的构造函数 

3. Function.prototype.bind(thisValue, params, param2...)

1)第一个参数

同call,apply方法

2)剩余的参数

当bind(thisValue, ...)后面参数的个数小于原函数的个数时,绑定部分参数;

// 绑定部分参数;相当于参数复用,只需要处理剩余的参数function fn(a,b) {    return a + b}var newFn = fn.bind(null, 5)/*    newFn = function(b) {        return 5 + b    }*/console.log(newFn(6)); // 11

3)应用

  • bind方法每次运行都返回一个新的函数;在监听事件时需要注意
    document.addEventListener('click', obj.fn.bind(this))// 下面取消绑定无效;因为是不同的函数document.removeEventListener('click',obj.fn.bind(this))

        正确的写法写法应该是

var listener = obj.fn.bind(this);document.addEventListener('click', listener);document.removeEventListener('click', listener);
  • 结合回调函数使用
    obj.print = function () {  this.times.forEach(function (n) {    console.log(this.name);  }.bind(this));};obj.print()// 张三// 张三// 张三
  • 和call方法结合使用;改变传参格式

    [1, 2, 3].slice(0, 1) // [1]// 等同于Array.prototype.slice.call([1, 2, 3], 0, 1) // [1]// 上面代码的意思是在Array.prototype.slice对象上调用call方法// 即var mySlice = Function.prototype.call.bind(Array.prototype.slice);console.log(mySlice([1,2,3], 0, 1))//同理var myPush = Function.prototype.call.bind(Array.prototype.push);// bind方法传参也可以被改变function f() {    console.log(this.a);}var obj = {a: 1}var myBind = Function.prototype.call.bind(Function.prototype.bind);myBind(f, obj)(); // 1

     

4. apply.call,bind之间的区别

1)call和apply方法调用后,相当于绑定this后立即执行

2)bind方法是返回一个新的函数,并不立即执行

应用:

1)将类数组转为数组

// 1)将类数组转为数组// apply,call方法立即执行Array.prototype.slice.apply({ 0: 1, length: 1,});Array.prototype.slice.call({ 0: 1, length: 1,});// bind方法生成一个新的函数,需要手动执行,后面加()Array.prototype.slice.bind({ 0: 1, length: 1,})();

2)给回调函数绑定对象

// 2)绑定回调函数的对象;// 未进行绑定前,回调函数中的this一般都是windowvar name = 'Hello World';var obj = {  name: 'Lyra',  times: [1,2,4],  print: function() {    console.log(this === obj); // true    this.times.forEach(function() {      console.log(this === window); // true       console.log(this.name);  // Hello World    })  }}obj.print(); // 使用bind方法绑定回调函数中的thisvar name = 'Hello World';var obj = {  name: 'Lyra',  times: [1,2,4],  print: function() {    this.times.forEach((function() {      console.log(this); // obj --3次      console.log(this.name);  // Lyra --3次    }.bind(this))) // 不能用call,apply替换,因为会立即执行,就不再是函数了,会返回函数的默认返回值undefined  }}obj.print(); // 使用call, apply方法绑定回调函数中的this;var name = 'Hello World';var obj = {  name: 'Lyra',  times: [1,2,4],  print: function() {    const that = this;    this.times.forEach((function() {
// 因为apply,call会立即执行,所以要嵌套一层函数 (function IIFE() { console.log(this); // obj --3次 console.log(this.name); // Lyra --3次 }).call(that); // 可以替换成apply。IIFE需要用括号扩起来变为函数表达式。否则函数声明不能调用call方法。 })) }}obj.print();

 

 

 

转载于:https://www.cnblogs.com/lyraLee/p/11441879.html

你可能感兴趣的文章
Teamcenter10 step-by-step installation in Linux env-Oracle Server Patch
查看>>
Redis-jedis模拟多线程购票
查看>>
聊一聊 Flex 中的 flex-grow、flex-shrink、flex-basis
查看>>
Gcc 安装过程中部分配置
查看>>
Logparser介绍
查看>>
Js实现客户端表单的验证
查看>>
python使用input()来接受字符串时一直报错“xxx is not defined”
查看>>
加解密与数据校验
查看>>
stm8s_IAP_xmode串口升级
查看>>
usb 编程知识 总结
查看>>
2016.7.15 落实字符及字符串读取的结果
查看>>
他看了几千份技术简历,愿意把技术简历的秘籍传授给你
查看>>
Struts2学习(三)
查看>>
学习Linux的第十二课时
查看>>
使用电子邮件模板
查看>>
IoC 依赖注入、以及在Spring中的实现
查看>>
机器学习 —— 概率图模型(贝叶斯网络)
查看>>
树、森林和二叉树的转换
查看>>
Array:Missing Number
查看>>
数列有序!
查看>>