JavaScript温故而知新——函数的4种调用方式

2,721 阅读2分钟

一、作为函数调用

  • 非严格模式下的调用上下文(this的值)是全局对象,严格模式thisundefined
function myFunction() {
    return this;
}
myFunction();   // 返回window对象

二、作用方法调用

  • 调用上下文为当前对象,即this指向当前对象
var calculator = {
    value1: 1,
    value2: 1,
    add: function() {
        // this指代当前对象
        this.result = this.value1 + this.value2;
    }
};
calculator.add()    // 调用add方法结算结果
calculator.result   // =>2

// 方括号(属性访问表达式)进行属性访问操作
calculator["add"]()
  • 嵌套函数作为函数调用,非严格模式下this是全局对象,严格模式下为undefined
var o = {
    m: function() {
        var self = this;                // 将this的值进行保存
        console.log(this === o);        // "true"
        f();                            // 调用嵌套函数f()
        
        function f() {
            console.log(this === o);    // "false": this的值为全局对象或`undefined`
            console.log(self === o);    // "true": self指向外部函数this的值
        }
    }
}

三、构造函数调用

  • 如果函数或者方法调用之前带有new关键字,它就构成构造函数调用。
  • 构造函数调用会创建一个新的空对象,并初始化这个新创建的对象,将这个对象用作其调用上下文。
var o = {
    m: function() {
        return 1;
    }
}
console.log(new o.m() === 1)    // "false"

在上面的代码中,尽管构造函数看起来像一个方法调用,但它依然会使用new出来的新对象作为调用上下文。也就是说,在表达式new o.m()中,调用上下文并不是o

四、间接调用

call()方法和apply()方法
call()apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数是要调用函数的母对象,它是调用上下文。

function myFunction(a, b) {
    return a * b;
}
myObject = myFunction.call(myObject, 10, 2);     // 返回 20
function myFunction(a, b) {
    return a * b;
}
myArray = [10, 2];
myObject = myFunction.apply(myObject, myArray);  // 返回 20

tip:

  • call()apply()区别在于第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)
  • 在严格模式下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。
  • 在非严格模下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。

结尾

系列文章: