JS apply call bind总结


一、apply

apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

func.apply(thisArg, [argsArray])

thisArg
必选的。在 func 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。

argsArray
可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象(需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受类数组对象。如果传入类数组对象,它们会抛出异常)。

  • 用 apply 修改方法的 this 指向
const firstName = "Ming";
const lastName = "Xiao";
const person = {
    firstName: "Mei",
    lastName: "Li",
    fullName: function(age, score, hobby) {
        return this.firstName + " " + this.lastName + "今年" + age + "岁,考了" + score + "分, 爱好是" + hobby + "。";
    }
}
const personInstance = {
    firstName: "Bill",
    lastName: "Gates",
}
console.log(person.fullName.apply(null, [12, 60, '足球']));  // 将返回 "Ming Xiao今年12岁,考了60分, 爱好是足球。"
console.log(person.fullName.apply(person, [13, 88, '跳舞']));  // 将返回 "Mei Li今年13岁,考了88分, 爱好是跳舞。"
console.log(person.fullName.apply(personInstance, [50, 90, '计算机']));  // 将返回 "Bill Gates今年50岁,考了90分, 爱好是计算机。"

如果按照上面代码去测试,后面两个返回是对的,但是第一个person.fullName.apply(null)并非预期的Xiao Ming, 而是undefined undefined。将最外层定义的 firstName 和 lastName 使用 var 定义就会达到预期,这块涉及到 ES6 const 和 let 的作用域和 JS this 指向的相关内容,有兴趣的大家去玩一玩、试一试。
MDN上还提供了三种示例:

  • 用 apply 将数组各项添加到另一个数组
  • 使用apply和内置函数
  • 使用apply来链接构造器
    大家可以到MDN 官网上去查看。

二、call

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

function.call(thisArg, arg1, arg2, ...)

thisArg
可选的。在 function 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。

arg1, arg2, …
指定的参数列表。

该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。

  • 用 apply 修改方法的 this 指向
const firstName = "Ming";
const lastName = "Xiao";
const person = {
    firstName: "Mei",
    lastName: "Li",
    fullName: function(age, score, hobby) {
        return this.firstName + " " + this.lastName + "今年" + age + "岁,考了" + score + "分, 爱好是" + hobby + "。";
    }
}
const personInstance = {
    firstName: "Bill",
    lastName: "Gates",
}
console.log(person.fullName.call(null, 12, 60, '足球'));  // 将返回 "Ming Xiao今年12岁,考了60分, 爱好是足球。"
console.log(person.fullName.call(person, 13, 88, '跳舞'));  // 将返回 "Mei Li今年13岁,考了88分, 爱好是跳舞。"
console.log(person.fullName.call(personInstance, 50, 90, '计算机'));  // 将返回 "Bill Gates今年50岁,考了90分, 爱好是计算机。"

MDN 关于 call() 的示例感觉还是实际场景见得更多一些:

  • 使用 call 方法调用父构造函数
function Product(name, price){
    this.name = name;
    this.price = price;
}

function Food(name, price){
    Product.call(this, name, price);
    Food.prototype = Product.prototype;
    this.category = 'food';
}
Food.prototype = new Product();
Food.prototype.constructor = Food;
Food.prototype.getInfo = function(){
    console.log(this.name +" "+ this.price + " " + this.category);
}

function Toy(name, price){
    Product.call(this, name, price);
    Toy.prototype = Product.prototype;
    this.category = 'toy';
}

Toy.prototype = new Product();
Toy.prototype.constructor = Toy;
Toy.prototype.getInfo = function(){
    console.log(this.name +" "+ this.price + " " + this.category);
}

let cheese = new Food('feta', 5);
let fun = new Toy('robot', 40);

cheese.getInfo()	// feta 5 food
fun.getInfo()	// robot 40 toy

我只是想使用一下call,关于JS的继承,原型链什么的,请自行去学习

  • 使用 call 方法调用匿名函数
const animals = [
    { species: 'Lion', name: 'King' },
    { species: 'Whale', name: 'Fail' }
];

for (let i = 0; i < animals.length; i++) {
    (function(i) {
        this.print = function() {
            console.log('#' + i + ' ' + this.species
                + ': ' + this.name);
        }
        this.print();
    }).call(animals[i], i);
}

三、bind

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

function.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg
调用绑定函数时作为 this 参数传递给目标函数的值。 如果使用new运算符构造绑定函数,则忽略该值。当使用 bind 在 setTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者thisArg是null或undefined,执行作用域的 this 将被视为新函数的 thisArg。

arg1, arg2, … 当目标函数被调用时,被预置入绑定函数的参数列表中的参数。

  • 创建绑定函数
    bind() 最简单的用法是创建一个函数,不论怎么调用,这个函数都有同样的 this 值。JavaScript新手经常犯的一个错误是将一个方法从对象中拿出来,然后再调用,期望方法中的 this 是原来的对象(比如在回调中传入这个方法)。如果不做特殊处理的话,一般会丢失原来的对象。基于这个函数,用原始的对象创建一个绑定函数,巧妙地解决了这个问题:
var name = "Xiao Ming"
const person = {
    name: 'Li Lei',
    getName: function() { return this.name; }
};
console.log(person.getName()); // Li Lei
const unboundGetName = person.getName;
console.log(unboundGetName());
// 返回 Xiao Ming - 因为函数是在全局作用域中调用的
// 创建一个新函数,把 'this' 绑定到 person 对象
const boundGetName = unboundGetName.bind(person);
console.log(boundGetName()); // Li Lei
  • 偏函数
    bind() 的另一个最简单的用法是使一个函数拥有预设的初始参数。只要将这些参数(如果有的话)作为 bind() 的参数写在 this 后面。当绑定函数被调用时,这些参数会被插入到目标函数的参数列表的开始位置,传递给绑定函数的参数会跟在它们后面。

  • 配合 setTimeout
    在默认情况下,使用 window.setTimeout() 时,this 关键字会指向 window (或 global)对象。当类的方法中需要 this 指向类的实例时,你可能需要显式地把 this 绑定到回调函数,就不会丢失该实例的引用。

总结

  • 三者都可以改变函数的this对象指向。
  • 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window或global。
  • 三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入。
  • bind 是返回绑定this之后的函数,便于稍后调用;apply 、call 则是立即执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值