js中的this,arguments, callee, caller

一张图,先捋一捋逻辑
在这里插入图片描述

arguments

在函数内部,有两个特殊的对象:arguments 和 this。arguments是一个类数组对象,包含着传入函数中的所有参数。在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数。
arguments对象只是与数组类似(它不是Array的实例)。可以使用方括号语法访问它的每个元素。

arguments[0]

没有传递值的命名参数将自动被赋予 undefined 值。这就跟定义了变量但又没有初始化一样。

arguments.callee

这个arguments对象还有一个明教callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。

一个使用arguments.callee的例子。

function factorial(num){ 
    if (num <=1) { 
        return 1; 
    } else { 
        return num * factorial(num-1) 
    } 
}

定义阶乘函数一般都要用到递归算法;,在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial耦合在了一起。为了消除这种紧密耦合的现象,可以像下面这样使用 arguments.callee。

function factorial(num){ 
    if (num <=1) { 
        return 1; 
    } else { 
        return num * arguments.callee(num-1) 
    } 
}

在这个重写后的 factorial()函数的函数体内,没有再引用函数名factorial。这样,无论引用函数时使用的是什么名字,都可以保证正常完成递归调用。

caller

ECMAScript 5 也规范化了另一个函数对象的属性:caller。除了 Opera 的早期版本不支持,其他浏览器都支持这个ECMAScript3并没有定义的属性。这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为 null

function outer(){ 
    inner();  
} 
 
function inner(){ 
    alert(inner.caller); 
} 
 
outer();

上面代码会导致警告框中显示 outer()函数的源代码。因为 outer()调用了 inter(),所以 inner.caller 就指向 outer()。为了降低耦合度,也可以通过 arguments.callee.caller 来访问相同的信息

function outer(){ 
    inner(); 
} 
 
function inner(){ 
    alert(arguments.callee.caller); 
}  
 
outer();

IE、Firefox、Chrome 和 Safari 的所有版本以及 Opera 9.6 都支持 caller 属性。

当函数在严格模式下运行时,访问 arguments.callee 会导致错误。ECMAScript 5 还定义了 arguments.caller 属性,但在严格模式下访问它也会导致错误,而在非严格模式下这个属性始终是 undefined。定义这个属性是为了分清 arguments.caller 和函数的 caller 属性。以上变化都是为 了加强这门语言的安全性,这样第三方代码就不能在相同的环境里窥视其他代码了。 严格模式还有一个限制:不能为函数的 caller 属性赋值,否则会导致错误。

老生常谈this的问题

  • 全局代码中的this指向 window
  • 单纯的函数调用,this指向全局对象,window
  • 作为对象的方法被调用时候指向调用调用他的对象。
  • new 声明构造函数的时候,this指向这个新创建的对象。
  • 在内部函数中,仍然指向全局对象winodw
  • 可以用call,apply,bind改变this的指向。

new操作符干了什么?

  1. 创建一个新对象;[var o = {};]
  2. 将构造函数的作用域赋给新对象(因此this指向了这个新对象)
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象。

留下箭头函数的问题。

此文结合上面脑图看效果更佳。

猜你喜欢

转载自blog.csdn.net/lihchweb/article/details/103731639