JS中的call()方法和apply()方法用法总结

241 阅读2分钟
this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向。
call方法:
语法:Function.call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明:
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj
指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply方法:
语法:Function.apply([thisObj[,argArray]])
定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明:
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj,
并且无法被传递任何参数。

call方法跟apply方法并没有明显区别,只是传递参数的形式不一样。
第一个参数是作用域;
call():一个一个的传递参数;
apply():以数组的形式传递。



2.常见用法
2.1. 调用函数
2.2. 将类数组对象转换成数组对象
2.3. 借用别人的方法
2.4. 绑定this指向
2.5. 继承
2.6.实现ES6 扩展运算符功能

2.1 调用函数

function foo() {
    console.log(this === window);
}

foo();  // true
foo.call(); //  true
foo.apply();    // true
// 在非严格模式下当我们第一个参数传递为null或undefined时,函数体内的this会指向默认的宿主对象,在浏览器中则是window
foo.call(null); // true
foo.call(undefined);    // true
2.2 将类数组对象转换成数组对象
运用[].slice.call()让这个aruments类数组有数组方法slice
function person(name, age, high) {
    console.log(arguments);    //  { '0': 'xiaoming', '1': 12, '2': '1.6m' }

    var arr = [].slice.apply(arguments);  
    //[].slice.apply === Array.prototype.apply === [].__proto__.slice
    console.log(arr);    // ["xiaoming", 12, "1.6m"]
}

person("xiaoming", 12, "1.6m");
2.3 借用别人方法

// 借用Math对象的max方法寻找数组中的最大值
var arr = [1, 2, 3, 4, 5, 6],
    max;

max = Math.max.apply(Math, arr);
console.log(max);    // 6
2.4 绑定this指向

var foo = {
    name: "foo",
    showName: function() {
        console.log(this.name);
    }
}

var bar = {
    name: "bar"
}

foo.showName.apply(bar);    // bar
2.5 继承

// 定义父类构造函数
var Father = function(name, age) {
    this.name = name;
    this.age = age;
};

// 定义子类构造函数
var Student = function(name, age, high) {
    // 继承父类
  Father.call(this, name, age);就是把Father的函数放到this(Student)中运行, name和age是Father的参数。
    this.high = high;
};

Student.prototype.message = function() {
    console.log("name: " + this.name + ",age: " + this.age + ",high: " + this.high);
}

new Student("xiaoming", 12, "1.6m").message();    // name: xiaoming,age: 12,high: 1.6m
2.6 实现ES6 扩展运算符功能

(_console = console).log.apply(_console, [1, 2, 3]);

2.7 改变函数执行上下文;将函数 fn 的执行上下文改为 obj 对象

***函数中的this指针将被替换为call或者apply的第一个参数。将函数 fn 的执行上下文改为 obj 对象,只需要将obj作为call或者apply的第一个参数传入即可。
1、function speak(fn, obj) {
return fn.call(obj,obj) //Hello, Rebecca!!!
}
 speak(
function () {return this.greeting + ', ' + this.name + '!!!';}, 
{greeting: 'Hello',name: 'Rebecca'})

2、function partial(fn, str1, str2) {
return function (str3) {
     return fn.call(this,str1,str2,str3)// Hello, Ellie!!!
}
     
}
var sayIt = function(greeting, name, punctuation) {  
    return greeting + ', ' + name + (punctuation || '!'); 
};
partial(sayIt, 'Hello', 'Ellie')('!!!');