工厂函数中对象名与this是否可互换?实例调用无报错原因问询
工厂函数里对象名和
this的那点事儿 这问题问得相当精准,我来给你拆解明白~
首先:对象名和this能不能随便互换?
答案是绝对不能,两者的本质和指向逻辑完全不一样:
- 你在工厂函数里定义的对象(比如你的
returnObject)是一个局部变量,它明确指向你手动创建的那个要返回的新对象,指向是固定的; - 而
this是JavaScript里的动态绑定关键字,它的指向完全取决于函数的调用方式:- 如果工厂函数是普通调用(比如
createNumber(5)),非严格模式下this指向全局对象(浏览器里是window,Node.js里是global),严格模式下this是undefined; - 如果是通过
new调用工厂函数(虽然工厂函数一般不用new),this会指向新创建的实例对象。
- 如果工厂函数是普通调用(比如
所以绝大多数场景下,两者根本不能互换,混用只会导致奇怪的bug。
那你的代码为什么能正常运行?
先把你的代码还原一下(应该是这样吧):
"use strict"; function createNumber(num) { const returnObject = { value: num, doubleIt() { return returnObject.value * 2; } }; return returnObject; } const newInstance = createNumber(5); console.log(newInstance.doubleIt()); // 输出10,完全正常
这里的核心是闭包在起作用!
当你在returnObject的doubleIt方法里引用returnObject时,这个方法作为工厂函数内部的函数,会捕获(保留)对工厂函数作用域的引用。哪怕工厂函数createNumber执行完毕,它的作用域并不会被销毁——因为newInstance.doubleIt还拿着这个作用域的引用,所以returnObject变量仍然能被访问到,而且它指向的就是newInstance本身(因为returnObject就是工厂函数返回给newInstance的那个对象)。
这就解释了为什么你调用newInstance.doubleIt()时不会报错:方法里的returnObject就是它自己所属的那个对象,闭包帮你把这个引用留住了。
再对比用this的情况
如果把doubleIt改成用this:
doubleIt() { return this.value * 2; }
这时候调用newInstance.doubleIt()也能正常运行,因为这时候this的指向是调用者newInstance。但两者的逻辑完全不同:
- 用
returnObject:不管你怎么调用doubleIt(哪怕把它单独拎出来调用),它都会用原来的那个returnObject对象:const standaloneDouble = newInstance.doubleIt; console.log(standaloneDouble()); // 仍然输出10 - 用
this:如果把方法单独拎出来调用,严格模式下this会变成undefined,直接报错:const standaloneDouble = newInstance.doubleIt; console.log(standaloneDouble()); // 报错:Cannot read property 'value' of undefined
最后总结
- 工厂函数里对象名和
this不能互换,两者的指向逻辑天差地别; - 你的代码能运行是闭包的功劳,方法捕获了工厂函数内的对象变量,保留了引用;
- 严格模式下不报错,是因为你访问的是合法的闭包变量,没有违反严格模式的规则。
内容的提问来源于stack exchange,提问作者DR01D
相关产品推荐
相关产品推荐

