JavaScript函數(shù)、閉包、原型、面向?qū)ο髮W習筆記
斷言
單元測試框架的核心是斷言方法,通常叫assert()。
該方法通常接收一個值--需要斷言的值,以及一個表示該斷言目的的描述。
如果該值執(zhí)行的結(jié)果為true,斷言就會通過;
否則,斷言就會被認為是失敗的。
通常用一個相應的通過(pass)/ 失?。╢ail)標記記錄相關的信息;
function assert(value, desc) {
let li = document.createElement('li');
li.className = value ? 'pass' : 'fail';
li.appendChild(document.createTextNode(desc));
document.getElementById('results').appendChild(li);
}
// 斷言函數(shù)
function assert(value, desc) {
if (value) {
console.log(`\033[32m ${desc} \033[0m`); // 斷言通過 綠色字體
} else {
console.log(`\033[31m ${desc} \033[0m`); // 斷言失敗 紅色字體
}
}
函數(shù)
- JavaScript是一門函數(shù)式語言
- 在JavaScript中,函數(shù)是第一型對象。函數(shù)可以共處,可以視作為其他任意類型的對象。就像普通的JavaScript數(shù)據(jù)類型,,函數(shù)可以被任意變量進行引用,或聲明成對象字面量,甚至可以將其作為函數(shù)參數(shù)進行傳遞。
- 函數(shù)是第一型對象
- 可以通過字面量進行創(chuàng)建。
- 可以賦值給變量、數(shù)組或其他對象的屬性。
- 可以作為參數(shù)傳遞給函數(shù)。
- 可以作為函數(shù)的返回值進行返回。
- 可以擁有動態(tài)創(chuàng)建并賦值的屬性。
- 命名一個函數(shù)時,該名稱在整個函數(shù)聲明范圍內(nèi)是有效的。如果函數(shù)聲明在頂層,window對象上的同名屬性則會引用到該函數(shù)。
- 所有的函數(shù)都有一個name屬性,該屬性保存的是該函數(shù)名稱的字符串。匿名函數(shù)的name屬性值為空。
- 在JavaScript中,作用域是由function進行聲明的,而不是代碼塊。聲明的作用域創(chuàng)建于代碼塊,但不是終結(jié)于代碼塊(其他語言是終結(jié)于代碼塊的)
if (window) {
var x = 123;
}
alert(x);
執(zhí)行代碼后,會彈出123,是因為JavaScript在大括號關閉處并沒有終止其作用域。
- 變量聲明的作用域開始于聲明的地方,結(jié)束于函數(shù)的結(jié)尾,與代碼嵌套無關。
- 命名函數(shù)的作用域是指聲明該函數(shù)的整個函數(shù)范圍,與代碼嵌套無關;
- 對于作用域聲明,全局上下文就像一個包含頁面所有代碼的超大型函數(shù)。
- 所有的函數(shù)調(diào)用都會傳遞兩個隱式參數(shù):argument和this
作為函數(shù)進行調(diào)用
如果一個數(shù)不是作為方法、構(gòu)造器、或者通過apply()或call()進行調(diào)用的,則認為它是“作為函數(shù)”進行調(diào)用的。
function ninja() {};
ninja()
var samurai = function() {};
samurai()
- 以這種方式調(diào)用時,函數(shù)的上下文是全局上下文---window對象。
作為方法進行調(diào)用
當一個函數(shù)被賦值給對象的一個屬性,并使用引用該函數(shù)的這個屬性進行調(diào)用時,那么函數(shù)就是作為該對象的一個方法進行調(diào)用的。
var 0 = {};
o.whatever = function() {};
o.whatever();
- 將函數(shù)作為對象的一個方法進行調(diào)用時,該對象就變成了函數(shù)上下文,并且在函數(shù)內(nèi)部可以以this參數(shù)的形式進行訪問。
作為構(gòu)造器進行調(diào)用
- 將函數(shù)作為構(gòu)造器進行調(diào)用,需要在函數(shù)調(diào)用前使用new關鍵字
創(chuàng)建一個新的空對象;
傳遞給構(gòu)造器都對象是this參數(shù),從而成為構(gòu)造器的函數(shù)上下文;
如果沒有顯式都返回值,新創(chuàng)建的對象則作為構(gòu)造器的返回值進行返回。
function Ninja() {
this.skulk = function() { return this; }
}
var ninja1 = new Ninja();
var ninja2 = new Ninja();
構(gòu)造器的目的是通過函數(shù)調(diào)用初始化創(chuàng)建新的對象。
函數(shù)調(diào)用方式差異
- 函數(shù)調(diào)用方式之間點主要差異是:作為this參數(shù)傳遞給執(zhí)行函數(shù)的上下文對象之間點區(qū)別。
作為方法調(diào)用,該上下文是方法的擁有者;
作為全局函數(shù)進行調(diào)用,其上下文永遠是window(也就說,該函數(shù)是window的一個方法)。
作為構(gòu)造器進行調(diào)用,其上下文對象則是新創(chuàng)建的對象實例。
使用apply()和call()方法
- 通過函數(shù)的apply()方法來調(diào)用函數(shù),需要給apply()傳入兩個參數(shù):一個是函數(shù)上下文的對象,另一個是作為函數(shù)參數(shù)所組成的數(shù)組;
- 通過函數(shù)的call()方法來調(diào)用函數(shù),需要給call()傳入兩個參數(shù):一個是函數(shù)上下文的對象,另一個是作為函數(shù)參數(shù)的參數(shù)列表,而不是單個數(shù)組;
function juggle() {
var result = 0;
for (var n = 0; n < arguments.length; n++) {
result += arguments[n]
}
this.result = result;
}
var ninja1 = {};
var ninja2 = {};
juggle.apply(ninja1, [1,2,3,4]);
juggle.call(ninja2, 5,6,7,8)
assert(ninja1.result === 10, 'juggled via apply');
assert(ninja2.result === 26, 'juggled via call');
使用apply()和call()可以選擇任意對象作為函數(shù)上下文;
函數(shù)總結(jié)
函數(shù)是第一型對象;
- 通過字面量進行創(chuàng)建。
- 賦值給變量或?qū)傩浴?/li>
- 作為參數(shù)進行傳遞。
- 作為函數(shù)結(jié)果進行返回。
- 擁有屬性和方法。
函數(shù)是通過字面量進行創(chuàng)建的,其名稱是可選的。
在頁面生命周期內(nèi),瀏覽器可以將函數(shù)作為各種類型的事件處理程序進行調(diào)用。
變量的作用域開始于聲明處,結(jié)束于函數(shù)尾部,其會跨域邊界(如:大括號)
內(nèi)部函數(shù)在當前函數(shù)的任何地方都可用(提升),即便是提前引用。
函數(shù)的形參列表和實際參數(shù)列表的長度可以是不同的。
- 未賦值的參數(shù)被設置為undefined。
- 多出的參數(shù)是不會綁定到參數(shù)名稱的。
每個函數(shù)調(diào)用都會傳入兩個隱式參數(shù)。
- arguments,實際傳入的參數(shù)集合。
- this,作為函數(shù)上下文的對象引用。
可以用不同的方法進行函數(shù)調(diào)用,不同的調(diào)用機制決定了函數(shù)上下文的不同。
- 作為普通函數(shù)進行調(diào)用時,其上下文是全局對象(window)。
- 作為方法進行調(diào)用時,其上下文是擁有該方法的對象。
- 作為構(gòu)造器進行調(diào)用時,其上下文是新分配的對象實例。
- 通過函數(shù)的apply()或call()方法進行調(diào)用時,上下文可以設置成任意值。
匿名函數(shù)
為了不讓不必要的函數(shù)名稱污染全局命名空間,可以創(chuàng)建大量的小型函數(shù)進行傳遞,而不是創(chuàng)建包含大量命令語句的大型函數(shù)。
遞歸
- 遞歸:當函數(shù)調(diào)用自身,或調(diào)用另外一個函數(shù),但這個函數(shù)的調(diào)用樹中的某個地方又調(diào)用到了自己時,就產(chǎn)生了遞歸。
- 遞歸的兩個條件:引用自身,并且有終止條件。
閉包
- 閉包是一個函數(shù)在創(chuàng)建時允許自身函數(shù)訪問并操作該自身函數(shù)之外的變量時所創(chuàng)建的作用域
- 閉包可以讓函數(shù)訪問所有的變量和函數(shù),只要這些變量和函數(shù)存在于該函數(shù)聲明時的作用域內(nèi)就行。
var outerValue = 'ninja';
var later;
function outerFunction() {
// 該變量的作用域限制在該函數(shù)內(nèi)部,并且在函數(shù)外部訪問不到;
var innerValue = 'samurai';
// 在外部函數(shù)內(nèi),聲明一個內(nèi)部函數(shù)。
// 注意:聲明該函數(shù)時,innerValue是在作用域內(nèi)的
function innerFunction() {
assert(outerValue, 'I can see the ninja');
assert(innerValue, 'I can see the samurai');
// 將內(nèi)部函數(shù)引用到later變量上,由于later在全局作用域內(nèi),所以可以對它進行調(diào)用。
later = innerFunction;
}
}
// 調(diào)用外部函數(shù),將會聲明內(nèi)部函數(shù),并將內(nèi)部函數(shù)賦值給later變量。
outerFunction();
// 通過later調(diào)用內(nèi)部函數(shù)。
// 我們不能直接調(diào)用內(nèi)部函數(shù),因為它的作用域(和innerValue一起)被限制在outerFunction內(nèi)。
later();
閉包使用場景:私有變量
在構(gòu)造器內(nèi)隱藏變量,使其在外部作用域不可訪問,但是可以存在于閉包內(nèi)。
function Ninja() {
var feints = 0;
this.getFenits = function() {
return feints;
}
this.feint = function() {
feints++;
}
}
var ninja = new Ninja();
ninja.feint();
assert(ninja.getFenits() === 1, '調(diào)用一次,內(nèi)部變量++');
assert(ninja.feints === undefined, '函數(shù)外部不可訪問')
變量的作用域依賴于變量所在的閉包
閉包記住的是變量的引用,而不是閉包創(chuàng)建時刻該變量的值
原型與面向?qū)ο?/strong>
- 所有的函數(shù)在初始化時都有一個prototype屬性,該屬性的初始值是一個空對象。
- 使用new操作符將函數(shù)作為構(gòu)造器進行調(diào)用的時候,其上下文被定義為新對象的實例。
- 在構(gòu)造器內(nèi)的綁定操作優(yōu)先級永遠高于在原型上的綁定操作優(yōu)先級。因為構(gòu)造器的this上下文指向的是實例自身,所以我們可以在構(gòu)造器內(nèi)對核心內(nèi)容執(zhí)行初始化操作。
- 通過instanceof操作,可以判斷函數(shù)是否繼承了其原型鏈中任何對象的功能。
- JavaScript創(chuàng)建對象方式總結(jié)【工廠模式、構(gòu)造函數(shù)模式、原型模式等】
- 淺談angularJs函數(shù)的使用方法(大小寫轉(zhuǎn)換,拷貝,擴充對象)
- JavaScript原型對象、構(gòu)造函數(shù)和實例對象功能與用法詳解
- js構(gòu)造函數(shù)創(chuàng)建對象是否加new問題
- js實現(xiàn)輪播圖的兩種方式(構(gòu)造函數(shù)、面向?qū)ο?
- 淺談JS封閉函數(shù)、閉包、內(nèi)置對象
- js eval函數(shù)使用,js對象和字符串互轉(zhuǎn)實例
- js中的eval()函數(shù)把含有轉(zhuǎn)義字符的字符串轉(zhuǎn)換成Object對象的方法
- 關于js函數(shù)解釋(包括內(nèi)嵌,對象等)
- js的對象與函數(shù)詳解
相關文章
JavaScript入門教程(5) js Screen屏幕對象
這是基本JavaScript的屏幕對象2009-01-01
JavaScript中使用concat()方法拼接字符串的教程
這篇文章主要介紹了JavaScript中使用concat()方法拼接字符串的教程,是JS入門學習中的基礎知識,需要的朋友可以參考下2015-06-06
javascript類型系統(tǒng)——undefined和null全面了解
下面小編就為大家?guī)硪黄猨avascript類型系統(tǒng)——undefined和null全面了解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-07-07
使用JavaScript 實現(xiàn)對象 勻速/變速運動的方法
本篇文章是對JavaScript中實現(xiàn)對象勻速/變速運動的方法進行了詳細的介紹。需要的朋友參考下2013-05-05

