關(guān)于作用域,我們需要注意以下幾個(gè)概念:
<code> var a = 10; function foo() { var b = 20; console.log(a); // 10 console.log(b); // 20 } foo(); console.log(a); // 10 console.log(b); // ReferenceError: b is not defined </code>
我們可以看到,變量a在全局作用域中聲明,因此在函數(shù)foo中也可以訪問(wèn)到它。而變量b則是在函數(shù)foo內(nèi)部聲明,只能在函數(shù)內(nèi)部訪問(wèn),無(wú)法在外部訪問(wèn)。
接下來(lái),讓我們看一下原型機(jī)制:
<code> function Foo() {} Foo.prototype.constructor === Foo; // true var foo = new Foo(); foo.constructor === Foo; // true foo.constructor === foo.__proto__.constructor; // true </code>
可以看到,每個(gè)函數(shù)在創(chuàng)建時(shí)都會(huì)創(chuàng)建一個(gè)prototype屬性,該屬性指向一個(gè)對(duì)象,這個(gè)對(duì)象就是原型對(duì)象。而每個(gè)實(shí)例對(duì)象都有一個(gè)__proto__屬性,該屬性指向它的構(gòu)造函數(shù)的原型對(duì)象。因此,我們可以通過(guò)實(shí)例對(duì)象的__proto__屬性來(lái)訪問(wèn)原型對(duì)象。
接下來(lái),我們看一下閉包:
<code> function foo() { var a = 10; function bar() { console.log(a); // 10 } return bar; } var test = foo(); test(); </code>
在foo函數(shù)中,定義了一個(gè)局部變量a和一個(gè)內(nèi)部函數(shù)bar,并將bar函數(shù)返回。由于bar函數(shù)內(nèi)部引用了外部函數(shù)的變量a,因此在全局范圍內(nèi)調(diào)用test函數(shù)時(shí),便可以訪問(wèn)函數(shù)foo內(nèi)部的局部變量a了。
最后,我們說(shuō)一下事件循環(huán):
<code> console.log('start'); setTimeout(function() { console.log('setTimeout'); }, 0); Promise.resolve().then(function() { console.log('promise'); }) console.log('end'); </code>
運(yùn)行上述代碼,我們會(huì)先輸出"start"和"end",然后輸出"promise"和"setTimeout"。這是因?yàn)镻romise的then方法會(huì)在主代碼執(zhí)行完后執(zhí)行,而setTimeout需要等到事件隊(duì)列清空后再執(zhí)行。
以上是JavaScript高級(jí)編程的一些筆記,希望能夠幫助讀者更好地學(xué)習(xí)和掌握J(rèn)avaScript。如果想要更深入地了解JavaScript高級(jí)編程,建議讀者閱讀經(jīng)典著作《JavaScript高級(jí)程序設(shè)計(jì)》。