JavaScript函数内部对象

JavaScript函数内部对象,ES6新增了 new.target 属性

在 ES5 中,函数内部有两个特殊对象:argumentsthis。ES6 新增了 new.target 属性。

arguments

一个类数组对象,包含调用函数时传入的所有参数。只有以 function 关键字定义函数时才会有 「换句话说:箭头函数中没有这个对象」

arguments.callee:一个指向 arguments 对象所在函数的指针。通过下面的例子加深了解

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 使用两种不同的方式,最后会输出相同的结果吗?
function factorial(num) {
if (num <= 1){
return 1;
} else {
// ===> 注意这里 方案一:
// return num * factorial(num - 1);
// ===> 注意这里 方案二:
return num * arguments.callee(num - 1);
}
}
let trueFn = factorial;
factorial = function (num){
return 0;
}
console.log(factorial(5)); // 输出 ?
console.log(trueFn(5)); // 输出 ?

注意:函数名就是指向函数的指针,一个函数可以又多个函数名

上面的例子

let trueFn = factorial; 这里把同一个函数的指针又保存到了另一个位置。trueFnfactorial 都是指向同一个函数的,只是函数名不同。

  • 方案一会造成函数逻辑与函数名高度耦合,即对函数的引用和函数名紧密耦合
    • 重写 factorial 函数后,factorialtrueFn 都会输出 0
  • 方案二会让函数逻辑与函数名解耦, 即对函数的引用和函数名无关,在严格模式下,arguments.callee 会报错
    • 重写 factorial 函数后,factorial 会输出 0, trueFn 会输出正确值 120.

this

标准函数中,this 指的是方法调用时的上下文对象(网页的全局上下文中,this 指向 window)

箭头函数中,this 指的是**定义箭头函数的上下文**

caller

这个属性引用的是调用当前函数的函数,或者如果是 在全局作用域中调用的则为 null

举个栗子:

1
2
3
4
5
6
7
8
function outer() {
inner();
}
function inner() {
console.log(inner.caller);
// console.log(arguments.callee.caller);// 解耦
}
outer();

ECMAScript 5 也定义了 arguments.caller,但 在严格模式下访问它会报错,在非严格模式下则始终是 undefined

上述代码最后会输出 outer 的源代码,因为 inner 是在 outer 中调用的,所以 inner.caller 指向 outer

new.target

ECMAScript 6 新增了检测函数是否使用 new 关键字调用的 new.target 属性。如果函数是正常调用的,则 new.target 的值是 undefined ;如果是使用 new 关键字调用的,则 new.target 将引用被调用的 构造函数。

1
2
3
4
5
6
7
8
function HelloWorld() {
if (!new.target) {
throw 'not using "new"'
}
console.log('using "new"');
}
new HelloWorld(); // using "new"
HelloWorld(); // Error:not using "new"'