JavaScript 工厂模式变量作用域
JavaScript 工厂模式变量作用域
我正在跟随一个教程,学习在javascript中使用工厂模式创建对象。下面的代码让我困惑,不知道为什么它可以工作。
我认为第一行注释的代码(在showLabel函数中使用this关键字)是正确的。使用obj替代它,我不确定为什么它可以工作。obj必须引用某个全局变量,因为在该函数运行时,没有定义obj,对吧?由于我创建了2个对象,不仅仅是这个例子的运行结果好,obj的内容的旧值也被存储并且正确地被引用。但是,如何做到的呢?如果我取消第二行注释,它就会出问题,我明白为什么,因为我在明确告诉js我正在谈论一个本地变量,而实际上并没有。
showLabel
函数中的obj
之所以有效,是因为它是一个局部变量。每次调用create address
时,该函数被声明。在JavaScript中,我们称之为闭包。
一般来说,原型对象的创建比使用工厂模式更受欢迎。
现在看看这个原型示例:
var Address = function(street, city, state, zip){ this.street = street; this.city = city; this.state = state; this.zip= zip; }; Address.prototype.showLabel = function(){ alert(this.street + "\n" + this.city + ", " + this.state + " " + this.zip); }
现在,当我使用new
关键字创建新地址时:
// create new address var address = new Address('1', '2', '3', '4'); address.showLabel(); // alert
代码将表现出您期望的行为。但是,如果我不使用new
关键字,则构造函数中的this
实际上是window
对象。
// create new address var address = Address('1', '2', '3', '4'); // address == undefined window.showLabel(); // address was added to window
我希望这可以帮助您理解一些事情。
欢迎来到闭包的世界。你对感觉什么感觉是对的,因为闭包的表现就好像是全局变量,但又不完全是全局变量。这就是闭包的行为。
在JavaScript中,当函数返回时,并不是所有的局部变量都像Java或C中一样会被垃圾回收/释放。如果有对该变量的引用,那么该变量将在其定义的函数作用域中存活。
从技术上讲,机制是不同的,有些人试图用这种方式来解释它,最终却混淆了许多其他人。对我来说,闭包是一种“私有”全局变量,就像全局变量一样,它们是在函数之间共享的,但它们没有声明在全局作用域中。就像你在遇到这个功能时所描述的感觉一样。
这里是我在stackoverflow上关于JavaScript闭包的一些其他答案,我认为值得一读:
或者你可以通过搜索“JavaScript闭包”来探索这个主题。
附加答案。
至于为什么this
在你的代码中起作用的解释(而不是尝试更正你的代码,以使this
可以起作用,即使在未更正的版本中它也是有效的 *咳咳* ;-):
JavaScript有延迟绑定。非常晚,非常非常晚。在编译时this
不仅没有绑定,在运行时也没有绑定。它是在执行时绑定的,也就是说直到函数被调用时,你才能知道this
实际上指向什么。调用者基本上决定了this
的值,而不是使用this
的函数。
一些神奇的JavaScript后期绑定操作:
function foo () { alert(this.bar); } var bar = "hello"; var obj = { foo : foo, bar : "hi" }; var second_obj = { bar : "bye" }; foo(); // says hello, 'this' refers to the global object and this.bar // refers to the global variable bar. obj.foo(); // says hi, 'this' refers to the first thing before the last dot // ie, the object foo belongs to // now this is where it gets weird, an object can borrow/steal methods of // another object and have its 'this' re-bound to it obj.foo.call(second_obj); // says bye because call and apply allows 'this' // to be re-bound to a foreign object. In this case // this refers to second_obj
在你的代码中,this
方便地引用调用函数的对象作为其方法,这就是为什么它可以工作,即使你似乎没有使用所谓的正确构造函数语法。