var name = "this window";
var object = {
name: "my object",
getNameFun: function(){
// return function(){
return this.name;
// }
}
}
console.log((object.getNameFun = object.getNameFun)()); //输出“this window”
console.log(object.getNameFun());//输出my object
上例中object.getNameFun = object.getNameFun)()是何意?为什么会输出this window?
var test;
var test1 = function test(){
var name = "test";
return function(){
var name = "test1";
return function(){
console.log(name);
}
}
}
console.log(test); //输出为undefined
console.log(test1); //输出为test函数
为什么上述代码中不能正确输出test,而是显示undefined,但是输出test1的时候却又正常输出test的呢?
一开始以为是test1替代了test,指向了这个函数结构,test指针所以为undefined,但是却发现输出test1不是匿名函数,而是test()函数?
求教~
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
搞懂这个问题当然要看ES规范,单纯考猜测和看一些书是不行的。
这个问题有两个关键点:
赋值表达式
(命名的)函数表达式
我们分别来看一下:
第一个问题:
首先是一个赋值表达式,然后是一个函数调用表达式。
首先看赋值表达式,根据规范:
https://es5.github.io/#x11.13.1
赋值表达式一共六个步骤,其他的不管,关键看第六步:表达式的结果就是
rval。这个rval是第三步得到的也就
GetValue(rref)。这个操作将一个引用类型取值了。相当于把object.getNameFun中的object.信息丢掉了,只返回了它的真实值,也就是那个函数对象。最终相当于:
结果很明显了。
第二个问题:
实际上定义了一个命名的函数表达式。
见:https://es5.github.io/#x13 中的第三种形式。而且规范里专门说了:
所以,test在外部是
undefined也非常明显了。不信你在函数体内打印一下。(object.getNameFun = object.getNameFun)()其中object.getNameFun = object.getNameFun是废话,自己赋值给自己,也就是说这句话的意思其实就是object.getNameFun(), 但是调用链却变成了全局对象中的方法被调用。this是关键字,是当前对象的引用值,什么是引用值?看看基础语法吧。输出
undefined的原因是你没有给test变量赋值。var test1 = function test(){},你已经都给test1赋值为test函数的引用了。var test1 = function () {},这才是匿名函数。多看看基础语法书吧...
http://bonsaiden.github.io/JavaScript-Garden/zh/#function.this
先回答第一个问题,在getNameFun里面加入console.log(this)后,重新执行你的方法
可以看到,第一次执行时,这里应该是一个自执行函数,实际this指向的是Window全局对象,而第二次执行时,实际this指向的是object这个方法这里是我理解错误了,这里应该可以理解为讲obejct.getNameFun赋值给obejct.getNameFun,然后执行,这是它的作用域就是指的window对象,而第二次是调用了object的getNameFun方法,它的作用域就是object对象
关于第二个问题,你可以看看这个:
函数声明与表达式
1.(object.getNameFun = object.getNameFun)()的作用是把函数赋给一个变量的同时执行此函数(也就是说,是单纯的执行一个函数,而不是到对象object里去执行getNameFun函数),在此时上下文环境是Window,而不是object。
为避免引起歧义,应该尽量不使用这种方式。
2.test是未赋值的变量,test1是函数,虽然函数名虽然是test但是在定义之初就赋值给了test1,所以函数test是没有生效的,test还是原先定义的变量
第1段代码:
(object.getNameFun = object.getNameFun)()我们先看一个括号运算符
(object.getNameFun = object.getNameFun)object.getNameFun绑定的函数对象赋值给object的getNameFun,这个没什么,关键点在于赋值运算符是否返回值得。这个赋值运算结束后返回的结果为object.getNameFun指向的函数对象;后面的括号,就是这个函数的调用运算符。和下面的代码等价
此时someFun调用时其this对象是全局对象,故输出结果为'''this window'''
这个和
(object.getNameFun)();调用是有区别的;(object.getNameFun)()等同于object.getNameFun()第2段代码:
是一个函数声明方式-函数表达式方式,其中的函数名是可选的。一旦使用函数名,这个函数名只在当前函数作用域内有效。所以
console.log(test); //输出为undefined,console.log(test1); //输出为test1的函数的字符串把代码修改下能看的更清楚些
问题一:
(object.getNameFun = object.getNameFun)()是何意?为什么会输出this window?object.getNameFun = object.getNameFun这条表达式将object.getNameFun赋值给自身,结果是输出了一个匿名函数:function () { return this.name; },而
(object.getNameFun = object.getNameFun)()意为直接调用这个匿名函数,由于前面没有指定调用对象,因此调用对象默认为全局对象window,this.name指向的是第一行定义的name,所以输出'this window'。问题二:为什么test为undefined?
第一行
var test;声明了test变量但未赋值,因此test默认为undefined。而下面的var test1 = function test() {...}是一个函数赋值表达式,其中的函数名test对外部是不可见的(详细原理可以参考JS的函数表达式机制),不会取代外部的test变量,因此test变量始终为undefined。问题三:为什么test1输出的是函数test()?
正如上面所说,函数表达式中指定了函数名test,对外部不可见,但对内部是可见的。test1引用了该test()函数,因此test1输出的也是
function test() {...}。