var length = 10 function fn () { console.log(this.length) } var obj = { length: 5, method (fn) { fn() arguments[0]() } } obj.method(fn, 1)
这一段代码会输出什么?
在非严格模式下,会分别输出10和2
在严格模式下和node、vue环境中会直接报错:length属性undefined
要理解为什么会出现这种情况,就需要理解this的作用域
普通函数的this是由动态作用域决定的,它总是指向它的直接调用者,具体可以分为:
1.this总是指向他的直接调用者,如arguments[0](),arguments[0]为arguments对象的第一个值,所以this指向arguments,输出的是arguments.length
2.如果函数没有直接调用者,如fn(1),在非严格模式下,this总是指向window,即使在method函数中重新定义fn函数,所以会输出window.length;
在严格模式下,this为undefined,undefined.length自然会报错
3.使用call,apply,bind绑定的,this指向的是绑定的对象
箭头函数的this是由静态作用域决定的,即始终指向定义函数时的作用域
arguments.length为什么为2
arguments对象包含传递给函数的每个参数,即函数的实参
obj.method(fn, 1)调用时传递了2个参数,所以arguments.length = 2
要注意的是this指向的是他的直接调用者,而非函数本身,函数fn的length会指明函数的形参个数
函数fn定义时没有参数,也就是没有形参,所以fn.length = 0
这里还有个隐藏的知识点
在严格模式下,剩余参数、默认参数和解构赋值参数的存在不会改变 arguments对象的行为,但是在非严格模式下就有所不同了。
具体可以参看 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments