JS闭包研究、自造困扰与解答
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script> //------------------------------------------------------------------ var intCount = 0; function Add() { return intCount++; } //------------------------------------------------------------------ var AddPkgErr = function () { var intCount = 0; //var intCountErr = 0; AddPkgErr.prototype.Add = function () { //return intCount++; return intCount++; //return intCountErr++; } } //------------------------------------------------------------------ var AddPkgOK = function () { //定義包的變量 AddPkgOK.prototype.intCount = 0; //AddPkgOK.prototype.intCountOK = 0; //定義包的方法 AddPkgOK.prototype.Add = function () { return AddPkgOK.prototype.intCount++; //return AddPkgOK.prototype.intCountOK++; } } var AddPkg3 = function () { //定義包的變量 this.intCount = 0; //定義包的方法 this.Add = function () { return this.intCount++; } } //==================================================================== function test1() { WriteLog("====================================="); WriteLog("非閉包,每次累加:" + Add()); } function test21() { WriteLog("====================================="); var objAddPkg = new AddPkgErr(); WriteLog("閉包單組21,每次都是新的:" + objAddPkg.Add()); } function test22() { WriteLog("====================================="); var objAddPkg = new AddPkgOK(); WriteLog("閉包單組22,每次都是新的:" + objAddPkg.Add()); } function test3() { WriteLog("====================================="); WriteLog("閉包多組,每組都是新的並且組與組之間互不影響(錯誤結果)"); var objAddPkg1 = new AddPkgErr(); WriteLog("第一組,第一次:" + objAddPkg1.Add()); WriteLog("第一組,第二次:" + objAddPkg1.Add()); WriteLog("第一組,第三次:" + objAddPkg1.Add()); WriteLog("====================================="); var objAddPkg2 = new AddPkgErr(); WriteLog("第二組,第一次:" + objAddPkg2.Add()); WriteLog("第二組,第二次:" + objAddPkg2.Add()); WriteLog("第二組,第三次:" + objAddPkg2.Add()); WriteLog("====================================="); WriteLog("第一組,第四次:" + objAddPkg1.Add()); WriteLog("第二組,第四次:" + objAddPkg2.Add()); } function test4() { WriteLog("====================================="); WriteLog("閉包多組,每組都是新的並且組與組之間互不影響(預期結果)"); var objAddPkg1 = new AddPkgOK(); WriteLog("第一組,第一次:" + objAddPkg1.Add()); WriteLog("第一組,第二次:" + objAddPkg1.Add()); WriteLog("====================================="); var objAddPkg2 = new AddPkgOK(); WriteLog("第二組,第一次:" + objAddPkg2.Add()); WriteLog("第二組,第二次:" + objAddPkg2.Add()); WriteLog("====================================="); WriteLog("第一組,第三次:" + objAddPkg1.Add()); WriteLog("第二組,第三次:" + objAddPkg2.Add()); } function test5() { WriteLog("====================================="); WriteLog("閉包多組,每組都是新的並且組與組之間互不影響(預期結果)"); var objAddPkg1 = new AddPkg3(); WriteLog("第一組,第一次:" + objAddPkg1.Add()); WriteLog("第一組,第二次:" + objAddPkg1.Add()); WriteLog("====================================="); var objAddPkg2 = new AddPkg3(); WriteLog("第二組,第一次:" + objAddPkg2.Add()); WriteLog("第二組,第二次:" + objAddPkg2.Add()); WriteLog("====================================="); WriteLog("第一組,第三次:" + objAddPkg1.Add()); WriteLog("第二組,第三次:" + objAddPkg2.Add()); } function WriteLog(sMsg) { txtMsg.innerHTML = txtMsg.innerHTML + sMsg + "\n"; } </script> </head> <body> <input id="btnTest1" type="button" onclick="test1();" value="非閉包" /> <input id="btnTest2" type="button" onclick="test21();" value="閉包單組" /> <input id="btnTest3" type="button" onclick="test22();" value="閉包單組" /> <input id="btnTest4" type="button" onclick="test3();" value="閉包多組多次(錯誤結果)" /> <input id="btnTest5" type="button" onclick="test4();" value="閉包多組多次(預期結果)" /> <input id="btnTest6" type="button" onclick="test5();" value="閉包多組多次(正确)" /> <input id="btnClear" type="button" onclick="txtMsg.innerHTML = '';" value="清空" /> <br /> <textarea id="txtMsg" rows="2" cols="20" style="width:100%; height:600px;"></textarea> </body> </html>
上面的代码关于“閉包多組多次(錯誤結果)”和“閉包多組多次(預期結果)”,红色字体结果都不是我预期的,还请教一下大家,感恩! 预期的结果应该是:
=====================================
閉包多組,每組都是新的並且組與組之間互不影響(預期結果)
第一組,第一次:0
第一組,第二次:1
=====================================
第二組,第一次:0
第二組,第二次:1
=====================================
第一組,第三次:2
第二組,第三次:3--->2(期望是2)
=====================================
閉包多組,每組都是新的並且組與組之間互不影響(錯誤結果)
第一組,第一次:0
第一組,第二次:1
第一組,第三次:2
=====================================
第二組,第一次:0
第二組,第二次:1
第二組,第三次:2
=====================================
第一組,第四次:3
第二組,第四次:4--->3(期望是3)
-----------------------------------------------------------
又仔细看了一边,真发现自己太粗心。
直接this就搞定了,唉。
人家明明写的:这时所有实例的type
属性和eat()
方法,其实都是同一个内存地址,指向prototype
对象,因此就提高了运行效率。
仔细思考应该可以认为:AddPkgErr中var intCount = 0;和AddPkgOK中AddPkgOK.prototype.intCount = 0;应该效果是一样的。
参考资料:
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html