javascript的apply和call方法,以及构造函数

javascript 的每个函数都包含两个非继承而来的方法:apply()call()。这两个方法都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值

apply() 函数

首先,apply() 方法接收两个参数:

  1. 运行函数的作用域 ( this ) 的值。
  2. 参数数组,这个参数可以是 Array 的实例,也可以是 arguments 对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function sum(num1, num2) {
return num1 + num2;
}

function callSum1(num1, num2) {
return sum.apply(this, arguments);
}

function callSum2(num1, num2) {
return sum.apply(this,[num1, num2])
}

console.log(callSum1(10, 10)); // 20
console.log(callSum2(10, 10)); // 20

上面的例子中, callSum1() 在执行 sum() 函数时传入了 this 作为 this 值(因为是在全局作用域中调用的,所以传入的就是 window 对象) 和 arguments 对象。而 callSum2 同样也调用了 sum() 函数,但它传入的是 this 和一个参数数组。这两个函数都会正常返回结果。

在严格模式下,未指定环境对象而调用函数,则 this 值不会转化为 window ,而是 undefined

call() 函数

call() 方法与 apply() 函数的作用相同,他们区别仅在于接收参数的方式不同。对于 call() 方法而言,第一个参数 this 值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用 call 方法时,传递给函数的参数必须逐个列举出来。

1
2
3
4
5
6
7
8
cafunction sum(num1, num2) {
return num1 + num2;
}

function callSum(num1, num2) {
return sum.call(this, num1, num2)
}
console.log(callSum(10, 10)); //20

对象的构造函数

下面是 Person 的构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name) ;
};
}
var person = Person("Bill Gates", 65, 'Software Enginerr');
var person1 = new Person('梅西', 29, 'football player');


上面第一种调用方法是 javascript 普通函数的调用方法,这里的 Person() 就是一个普通的 javascirpt 函数,调用过程中 thiswindow 对象,这里不会返回任何的对象,最后person 的值是 undefined

按普通函数调用

第二种调用方法主要经历了一下 4 个步骤:


  1. 创建一个新对象,暂时命名为 person 。
  2. 将构造函数的作用域附给了新的对象(如果使用 call 方法来调用,也就是 Person.call(person,'梅西', 29, 'football player' ))
  3. 执行构造函数中的代码。
  4. 返回新的对象。

查看运行过程,我们发现 this 指向新创建的的 person 对象。

按构造函数调用

任何函数,只要通过 new 操作符来调用,那就可以当做构造函数;而任何函数,如果不通过 new 操作符来调用,那它跟普通函数也不会有什么两样

作者

Bruce Liu

发布于

2019-01-31

更新于

2022-11-12

许可协议

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.