国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

重新復(fù)習(xí)js

xuexiangjys / 2640人閱讀

摘要:復(fù)習(xí)基礎(chǔ)到底是什么的應(yīng)用場合極其廣泛。常量不可以通過重新賦值改變其值,也不可以在代碼運行時重新聲明。布爾對象是原始布爾數(shù)據(jù)類型的一個包裝器整數(shù)整數(shù)可以用十進制基數(shù)為十六進制基數(shù)為八進制基數(shù)為以及二進制基數(shù)為表示。

復(fù)習(xí)js day1 js基礎(chǔ) JavaScript 到底是什么

JavaScript 的應(yīng)用場合極其廣泛。簡單到幻燈片、照片庫、浮動布局和響應(yīng)按鈕點擊。復(fù)雜到游戲、2D 和 3D 動畫、大型數(shù)據(jù)庫驅(qū)動程序,等等。

JavaScript 相當簡潔,卻非常靈活。開發(fā)者們基于 JavaScript 核心編寫了大量實用工具,可以使 開發(fā)工作事半功倍。其中包括:

瀏覽器應(yīng)用程序接口(API)—— 瀏覽器內(nèi)置的 API 提供了豐富的功能,比如:動態(tài)創(chuàng)建 HTML 和設(shè)置 CSS 樣式、從用戶的攝像頭采集處理視頻流、生成3D 圖像與音頻樣本,等等。

第三方 API —— 讓開發(fā)者可以在自己的站點中整合其它內(nèi)容提供者(Twitter、Facebook 等)提供的功能。

第三方框架和庫 —— 用來快速構(gòu)建網(wǎng)站和應(yīng)用。

變量 變量的定義和數(shù)據(jù)類型

在應(yīng)用程序中,使用變量來作為值的符號名。變量的名字又叫做標識符,其需要遵守一定的規(guī)則。

一個 JavaScript 標識符必須以字母、下劃線(_)或者美元符號($)開頭;后續(xù)的字符也可以是數(shù)字(0-9)。因為 JavaScript 語言是區(qū)分大小寫的,所以字母可以是從“A”到“Z”的大寫字母和從“a”到“z”的小寫字母。

變量 解釋
string 字符串(一串文本)。字符串的值必須將用引號(單雙均可,必須成對)擴起來。
Number 數(shù)字。無需引號。
Boolean 布爾值(真 / 假)。 true/false 是 JS 里的特殊關(guān)鍵字,無需引號。
Array 數(shù)組,用于在單一引用中存儲多個值的結(jié)構(gòu)
Object 對象,JavaScript 里一切皆對象,一切皆可儲存在變量里。這一點要牢記于心。
數(shù)據(jù)類型的轉(zhuǎn)換

字符串轉(zhuǎn)換為數(shù)字
有一些方法可以將內(nèi)存中表示一個數(shù)字的字符串轉(zhuǎn)換為對應(yīng)的數(shù)字。parseInt()和parseFloat()

parseInt 方法只能返回整數(shù),所以使用它會丟失小數(shù)部分。另外,調(diào)用 parseInt 時最好總是帶上進制(radix) 參數(shù),這個參數(shù)用于指定使用哪一種進制。

將字符串轉(zhuǎn)換為數(shù)字的另一種方法是使用一元加法運算符。

"1.1" + "1.1" = "1.11.1"
(+"1.1") + (+"1.1") = 2.2   
// 注意:加入括號為清楚起見,不是必需的。
聲明變量

var 聲明全局變量和局部變量
let 聲明塊作用域的局部變量
const 聲明一個常量

使用var和let聲明的變量時沒有賦予初始值的,其值為undefined,

var a;
console.log("The value of a is " + a); // a 的值是 undefined

console.log("The value of b is " + b);// b 的值是 undefined 
var b;


console.log("The value of c is " + c); // 未捕獲的引用錯誤: c 未被定義

let x;
console.log("The value of x is " + x); // x 的值是 undefined

console.log("The value of y is " + y);// 未捕獲的引用錯誤: y 未被定義
let y;

你可以使用 undefined 來判斷一個變量是否已賦值。在以下的代碼中,變量input未被賦值,因此 if 條件語句的求值結(jié)果是 true

var input;
if(input === undefined){
  doThis();
} else {
  doThat();
}

undefined 值在布爾類型環(huán)境中會被當作 false 。

數(shù)值類型環(huán)境中 undefined 值會被轉(zhuǎn)換為 NaN。

當你對一個 null 變量求值時,空值 null 在數(shù)值類型環(huán)境中會被當作0來對待,而布爾類型環(huán)境中會被當作 false

var n = null;
console.log(n * 32); // 在控制臺中會顯示 0

變量的作用域

在函數(shù)之外聲明的變量,叫做全局變量,因為它可被當前文檔中的任何其他代碼所訪問。在函數(shù)內(nèi)部聲明的變量,叫做局部變量,因為它只能在當前函數(shù)的內(nèi)部訪問。

ECMAScript 6 之前的 JavaScript 沒有 語句塊 作用域;相反,語句塊中聲明的變量將成為語句塊所在函數(shù)(或全局作用域)的局部變量。例如,如下的代碼將在控制臺輸出 5,因為 x 的作用域是聲明了 x 的那個函數(shù)(或全局范圍),而不是 if 語句塊。

if (true) {
  var x = 5;
}
console.log(x); // 5

如果使用 ECMAScript 6 中的 let 聲明,上述行為將發(fā)生變化。

if (true) {
  let y = 5;
}
console.log(y); // ReferenceError: y 沒有被聲明
變量提升

JavaScript 變量的另一個不同尋常的地方是,你可以先使用變量稍后再聲明變量而不會引發(fā)異常。這一概念稱為變量提升;JavaScript 變量感覺上是被“提升”或移到了函數(shù)或語句的最前面。但是,提升后的變量將返回 undefined 值。因此在使用或引用某個變量之后進行聲明和初始化操作,這個被提升的變量仍將返回 undefined 值。

/**
 * 例子1
 */
console.log(x === undefined); // true
var x = 3;


/**
 * 例子2
 */
// will return a value of undefined
var myvar = "my value";

(function() {
  console.log(myvar); // undefined
  var myvar = "local value";
})();


//詳細解釋就是
/**
 * 例子1
 */
var x;
console.log(x === undefined); // true
x = 3;
 
/**
 * 例子2
 */
var myvar = "my value";
 
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "local value";
})();

由于存在變量提升,一個函數(shù)中所有的var語句應(yīng)盡可能地放在接近函數(shù)頂部的地方。這個習(xí)慣將大大提升代碼的清晰度。

在 ECMAScript 6 中,let(const)將不會提升變量到代碼塊的頂部。因此,在變量聲明之前引用這個變量,將拋出引用錯誤(ReferenceError)。這個變量將從代碼塊一開始的時候就處在一個“暫時性死區(qū)”,直到這個變量被聲明為止。

console.log(x); // ReferenceError
let x = 3;
函數(shù)提升

對于函數(shù)來說,只有函數(shù)聲明會被提升到頂部,而函數(shù)表達式不會被提升。

/* 函數(shù)聲明 */

foo(); // "bar"

function foo() {
  console.log("bar");
}


/* 函數(shù)表達式 */

baz(); // 類型錯誤:baz 不是一個函數(shù)

var baz = function() {
  console.log("bar2");
};
常量

你可以用關(guān)鍵字 const 創(chuàng)建一個只讀的常量。常量標識符的命名規(guī)則和變量相同:必須以字母、下劃線(_)或美元符號($)開頭并可以包含有字母、數(shù)字或下劃線。

const PI = 3.14;

常量不可以通過重新賦值改變其值,也不可以在代碼運行時重新聲明。它必須被初始化為某個值。

常量的作用域規(guī)則與 let 塊級作用域變量相同。若省略const關(guān)鍵字,則該標識符將被視為變量。

在同一作用域中,不能使用與變量名或函數(shù)名相同的名字來命名常量。

然而,對象屬性被賦值為常量是不受保護的,所以下面的語句執(zhí)行時不會產(chǎn)生錯誤。

const MY_OBJECT = {"key": "value"};
MY_OBJECT.key = "otherValue";

同樣的,數(shù)組的被定義為常量也是不受保護的,所以下面的語句執(zhí)行時也不會產(chǎn)生錯誤。

const MY_ARRAY = ["HTML","CSS"];
MY_ARRAY.push("JAVASCRIPT");
console.log(MY_ARRAY); //logs ["HTML","CSS","JAVASCRIPT"];
字面量 (Literals)

譯注:字面量是由語法表達式定義的常量;或,通過由一定字詞組成的語詞表達式定義的常量

在JavaScript中,你可以使用各種字面量。這些字面量是腳本中按字面意思給出的固定的值,而不是變量。(譯注:字面量是常量,其值是固定的,而且在程序腳本運行中不可更改

數(shù)組字面量 (Array literals)

數(shù)組字面值是一個封閉在方括號對([])中的包含有零個或多個表達式的列表,其中每個表達式代表數(shù)組的一個元素。當你使用數(shù)組字面值創(chuàng)建一個數(shù)組時,該數(shù)組將會以指定的值作為其元素進行初始化,而其長度被設(shè)定為元素的個數(shù)。

下面的示例用3個元素生成數(shù)組coffees,它的長度是3。

var coffees = ["French Roast", "Colombian", "Kona"];

var a=[3];

console.log(a.length); // 1

console.log(a[0]); // 3
//注意 這里的數(shù)組字面值也是一種對象初始化器。

若在頂層(全局)腳本里用字面值創(chuàng)建數(shù)組,JavaScript語言將會在每次對包含該數(shù)組字面值的表達式求值時解釋該數(shù)組。另一方面,在函數(shù)中使用的數(shù)組,將在每次調(diào)用函數(shù)時都會被創(chuàng)建一次。

數(shù)組字面值同時也是數(shù)組對象。有關(guān)數(shù)組對象的詳情請參見數(shù)組對象一文。

數(shù)組字面值中的多余逗號
(譯注:聲明時)你不必列舉數(shù)組字面值中的所有元素。若你在同一行中連寫兩個逗號(,),數(shù)組中就會產(chǎn)生一個沒有被指定的元素,其初始值是undefined。以下示例創(chuàng)建了一個名為fish的數(shù)組:

var fish = ["Lion", , "Angel"];

在這個數(shù)組中,有兩個已被賦值的元素,和一個空元素(fish[0]是"Lion",fish[1]是undefined,而fish[2]是"Angel";譯注:此時數(shù)組的長度屬性fish.length是3)。

如果你在元素列表的尾部添加了一個逗號,它將會被忽略。在下面的例子中,數(shù)組的長度是3,并不存在myList[3]這個元素(譯注:這是指數(shù)組的第4個元素噢,作者是在幫大家復(fù)習(xí)數(shù)組元素的排序命名方法)。元素列表中其它所有的逗號都表示一個新元素(的開始)。

注意:尾部的逗號在早期版本的瀏覽器中會產(chǎn)生錯誤,因而編程時的最佳實踐方式就是移除它們。

(譯注:而“現(xiàn)代”的瀏覽器似乎鼓勵這種方式,這也很好解釋原因。尾部逗號可以減少向數(shù)組的最后添加元素時,因為忘記為這最后一個元素加逗號 所造成的錯誤。)

var myList = ["home", , "school", ];

在下面的例子中,數(shù)組的長度是4,元素myList[0]和myList[2]缺失(譯注:沒被賦值,因而是undefined)。

var myList = [ , "home", , "school"];

再看一個例子。在這里,該數(shù)組的長度是4,元素myList[1]和myList[3]被漏掉了。(但是)只有最后的那個逗號被忽略。

var myList = ["home", , "school", , ];

理解多余的逗號(在腳本運行時會被如何處理)的含義,對于從語言層面理解JavaScript是十分重要的。但是,在你自己寫代碼時:顯式地將缺失的元素聲明為undefined,將大大提高你的代碼的清晰度和可維護性。

布爾字面量 (Boolean literals)

布爾類型有兩種字面量:true和false。

不要混淆作為布爾對象的真和假與布爾類型的原始值true和false。布爾對象是原始布爾數(shù)據(jù)類型的一個包裝器

整數(shù) (Integers)

整數(shù)可以用十進制(基數(shù)為10)、十六進制(基數(shù)為16)、八進制(基數(shù)為8)以及二進制(基數(shù)為2)表示。

十進制整數(shù)字面量由一串數(shù)字序列組成,且沒有前綴0。

八進制的整數(shù)以 0(或0O、0o)開頭,只能包括數(shù)字0-7。

十六進制整數(shù)以0x(或0X)開頭,可以包含數(shù)字(0-9)和字母 a~f 或 A~F。

二進制整數(shù)以0b(或0B)開頭,只能包含數(shù)字0和1。

嚴格模式下,八進制整數(shù)字面量必須以0o或0O開頭,而不能以0開頭。

整數(shù)字面量舉例:

0, 117 and -345 (十進制, 基數(shù)為10)
015, 0001 and -0o77 (八進制, 基數(shù)為8)
0x1123, 0x00111 and -0xF1A7 (十六進制, 基數(shù)為16或"hex")
0b11, 0b0011 and -0b11 (二進制, 基數(shù)為2)
對象字面量 (Object literals)

對象字面值是封閉在花括號對({})中的一個對象的零個或多個"屬性名-值"對的(元素)列表。你不能在一條語句的開頭就使用對象字面值,這將導(dǎo)致錯誤或產(chǎn)生超出預(yù)料的行為, 因為此時左花括號({)會被認為是一個語句塊的起始符號。(譯者:這 里需要對語句statement、塊block等基本名詞的解釋)

以下是一個對象字面值的例子。對象car的第一個元素(譯注:即一個屬性/值對)定義了屬性myCar;第二個元素,屬性getCar,引用了一個函數(shù)(即CarTypes("Honda"));第三個元素,屬性special,使用了一個已有的變量(即Sales)。

var Sales = "Toyota";

function CarTypes(name) {
  return (name === "Honda") ?
    name :
    "Sorry, we don"t sell " + name + "." ;
}

var car = { myCar: "Saturn", getCar: CarTypes("Honda"), special: Sales };

console.log(car.myCar);   // Saturn
console.log(car.getCar);  // Honda
console.log(car.special); // Toyota

更進一步的,你可以使用數(shù)字或字符串字面值作為屬性的名字,或者在另一個字面值內(nèi)嵌套上一個字面值。如下的示例中使用了這些可選項。

var car = { manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };

console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda

對象屬性名字可以是任意字符串,包括空串。如果對象屬性名字不是合法的javascript標識符,它必須用""包裹。屬性的名字不合法,那么便不能用.訪問屬性值,而是通過類數(shù)組標記("[]")訪問和賦值。

var unusualPropertyNames = {
  "": "An empty string",
  "!": "Bang!"
}
console.log(unusualPropertyNames."");   // 語法錯誤: Unexpected string
console.log(unusualPropertyNames[""]);  // An empty string
console.log(unusualPropertyNames.!);    // 語法錯誤: Unexpected token !
console.log(unusualPropertyNames["!"]); // Bang!
字符串字面量 (String literals)

字符串字面量是由雙引號(")對或單引號(")括起來的零個或多個字符。字符串被限定在同種引號之間;也即,必須是成對單引號或成對雙引號。下面的例子都是字符串字面值:

"foo"
"bar"
"1234"
"one line 
 another line"
"John"s cat"

你可以在字符串字面值上使用字符串對象的所有方法——JavaScript會自動將字符串字面值轉(zhuǎn)換為一個臨時字符串對象,調(diào)用該方法,然后廢棄掉那個臨時的字符串對象。你也能用對字符串字面值使用類似String.length的屬性:

console.log("John"s cat".length) 
// 將打印字符串中的字符個數(shù)(包括空格) 
// 結(jié)果為:10

在ES2015中,還提供了一種模板字符串(template literals),模板字符串提供了一些語法糖來幫你構(gòu)造字符串。這與Perl、Python還有其他語言中的字符串插值(string interpolation)的特性非常相似。除此之外,你可以在通過模板字符串前添加一個tag來自定義模板字符串的解析過程,這可以用來防止注入攻擊,或者用來建立基于字符串的高級數(shù)據(jù)抽象。

// Basic literal string creation
`In JavaScript "
" is a line-feed.`

// Multiline strings
`In JavaScript this is
 not legal.`

// String interpolation
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

// Construct an HTTP request prefix is used to interpret the replacements and construction
POST`http://foo.org/bar?a=${a}&b=${b}
     Content-Type: application/json
     X-Credentials: ${credentials}
     { "foo": ${foo},
       "bar": ${bar}}`(myOnReadyStateChangeHandler);

除非有特別需要使用字符串對象,否則,你應(yīng)當始終使用字符串字面值。

js流程控制與錯誤處理 條件判斷語句

條件判斷語句指的是根據(jù)指定的條件所返回的結(jié)果(真或假或其它預(yù)定義的),來執(zhí)行特定的語句。JavaScript 支持兩種條件判斷語句:if...else和switch。

let iceCream = "chocolate";
if (iceCream === "chocolate") {
  alert("我最喜歡巧克力冰激淋了。");    
} else {
  alert("但是巧克力才是我的最愛呀……");    
}
異常處理語句

你可以用 throw 語句拋出一個異常并且用 try...catch 語句捕獲處理它。

throw 語句

try...catch 語句

Promises

從 ECMAScript 6 開始,JavaScript 增加了對 Promise 對象的支持,它允許你對延時和異步操作流進行控制。

Promise 對象有以下幾種狀態(tài):

pending:初始的狀態(tài),即正在執(zhí)行,不處于 fulfilled 或 rejected 狀態(tài)。

fulfilled:成功的完成了操作。

rejected:失敗,沒有完成操作。

settled:Promise 處于 fulfilled 或 rejected 二者中的任意一個狀態(tài), 不會是 pending。

展現(xiàn)了 Promise 的工作流

function imgLoad(url) {
  return new Promise(function(resolve, reject) {
    var request = new XMLHttpRequest();
    request.open("GET", url);
    request.responseType = "blob";
    request.onload = function() {
      if (request.status === 200) {
        resolve(request.response);
      } else {
        reject(Error("Image didn"t load successfully; error code:" 
                     + request.statusText));
      }
    };
    request.onerror = function() {
      reject(Error("There was a network error."));
    };
    request.send();
  });
}
循環(huán)和迭代

JavaScript中提供了這些循環(huán)語句:

for 語句

do...while 語句

while 語句

labeled 語句

break 語句

continue 語句

for...in 語句

for...of 語句

for 語句

一個for循環(huán)會一直重復(fù)執(zhí)行,直到指定的循環(huán)條件為fasle。 JavaScript的for循環(huán)和Java與C的for循環(huán)是很相似的。

for ([initialExpression]; [condition]; [incrementExpression])
statement

當一個for循環(huán)執(zhí)行的時候,會發(fā)生以下事件:

如果有初始化表達式initialExpression,它將被執(zhí)行。這個表達式通常會初始化一個或多個循環(huán)計數(shù)器,但語法上是允許一個任意復(fù)雜度的表達式的。這個表達式也可以聲明變量。

計算condition表達式的值。如果condition的值是true,循環(huán)中的statement會被執(zhí)行。如果condition的值是false,for循環(huán)終止。如果condition表達式整個都被省略掉了,condition的值會被認為是true。

循環(huán)中的 statement被執(zhí)行。如果需要執(zhí)行多條語句,可以使用塊 ({ ... })來包裹這些語句。

如果有更新表達式incrementExpression,執(zhí)行它.

然后流程回到步驟2。

do...while

do...while 語句一直重復(fù)直到指定的條件求值得到假(false)。 一個 do...while 語句看起來像這樣:

do
  statement
while (condition);

statement 在檢查條件之前會執(zhí)行一次。要執(zhí)行多條語句(語句塊),要使用塊語句 ({ ... }) 包括起來。 如果 condition 為真(true),statement 將再次執(zhí)行。 在每個執(zhí)行的結(jié)尾會進行條件的檢查。當 condition 為假(false),執(zhí)行會停止并且把控制權(quán)交回給 do...while 后面的語句。

在下面的例子中, 這個 do 循環(huán)將至少重復(fù)一次并且一直重復(fù)直到 i 不再小于 5。

do {
  i += 1;
  console.log(i);
} while (i < 5);
while 語句

一個 while 語句只要指定的條件求值為真(true)就會一直執(zhí)行它的語句塊。一個 while 語句看起來像這樣:

while (condition)

statement

如果這個條件變?yōu)榧伲h(huán)里的 statement 將會停止執(zhí)行并把控制權(quán)交回給 while 語句后面的代碼。

條件檢測會在每次 statement 執(zhí)行之前發(fā)生。如果條件返回為真, statement 會被執(zhí)行并緊接著再次測試條件。如果條件返回為假,執(zhí)行將停止并把控制權(quán)交回給 while 后面的語句。

要執(zhí)行多條語句(語句塊),要使用塊語句 ({ ... }) 包括起來。

例子 1
下面的 while 循環(huán)只要 n 小于 3就會一直執(zhí)行:

var n = 0;
var x = 0;
while (n < 3) {
  n++;
  x += n;
}

在每次循環(huán)里, n 會增加1并被加到 x 上。所以, x 和 n 的變化是:

第一次完成后: n = 1 和 x = 1

第二次完成后: n = 2 和 x = 3

第三次完成后: n = 3 和 x = 6

在三次完成后, 條件 n < 3 結(jié)果不再為真,所以循環(huán)終止了。

例子 2
避免無窮循環(huán)(無限循環(huán))。保證循環(huán)的條件結(jié)果最終會變成假;否則,循環(huán)永遠不會停止。下面這個 while 循環(huán)會永遠執(zhí)行因為條件永遠不會變成假:

while (true) {
  console.log("Hello, world");
}
函數(shù)

函數(shù) 用來封裝可復(fù)用的功能。如果沒有函數(shù),一段特定的操作過程用幾次就要重復(fù)寫幾次,而使用函數(shù)則只需寫下函數(shù)名和一些簡短的信息

瀏覽器內(nèi)置函數(shù)和用戶定義的函數(shù)

定義函數(shù) 函數(shù)聲明

一個函數(shù)定義(也稱為函數(shù)聲明,或函數(shù)語句)由一系列的function關(guān)鍵字組成,依次為:

函數(shù)的名稱。

函數(shù)參數(shù)列表,包圍在括號中并由逗號分隔。

定義函數(shù)的 JavaScript 語句,用大括號{}括起來。

例如,以下的代碼定義了一個簡單的square函數(shù):

function square(number) {
  return number * number;
}

函數(shù)square使用了一個參數(shù),叫作number。這個函數(shù)只有一個語句,它說明該函數(shù)將函數(shù)的參數(shù)(即number)自乘后返回。函數(shù)的return語句確定了函數(shù)的返回值:

return number * number;

原始參數(shù)(比如一個具體的數(shù)字)被作為值傳遞給函數(shù);值被傳遞給函數(shù),如果被調(diào)用函數(shù)改變了這個參數(shù)的值,這樣的改變不會影響到全局或調(diào)用函數(shù)。

如果你傳遞一個對象(即一個非原始值,例如Array或用戶自定義的對象)作為參數(shù),而函數(shù)改變了這個對象的屬性,這樣的改變對函數(shù)外部是可見的,如下面的例子所示:

function myFunc(theObject) {
  theObject.make = "Toyota";
}

var mycar = {make: "Honda", model: "Accord", year: 1998};
var x, y;

x = mycar.make;     // x獲取的值為 "Honda"

myFunc(mycar);
y = mycar.make;     // y獲取的值為 "Toyota"
                    // (make屬性被函數(shù)改變了)
函數(shù)表達式

雖然上面的函數(shù)聲明在語法上是一個語句,但函數(shù)也可以由函數(shù)表達式創(chuàng)建。這樣的函數(shù)可以是匿名的;它不必有一個名稱。例如,函數(shù)square也可這樣來定義:

var square = function(number) { return number * number; };
var x = square(4); // x gets the value 16

然而,函數(shù)表達式也可以提供函數(shù)名,并且可以用于在函數(shù)內(nèi)部代指其本身,或者在調(diào)試器堆棧跟蹤中識別該函數(shù):

var factorial = function fac(n) {return n<2 ? 1 : n*fac(n-1)};

console.log(factorial(3));

當將函數(shù)作為參數(shù)傳遞給另一個函數(shù)時,函數(shù)表達式很方便。下面的例子演示了一個叫map的函數(shù)如何被定義,而后使用一個表達式函數(shù)作為其第一個參數(shù)進行調(diào)用:

function map(f,a) {
  var result = [],i; //創(chuàng)建一個新數(shù)組
  for (i = 0; i != a.length; i++)
    result[i] = f(a[i]);
  return result;
}

下面的代碼:

function map(f, a) {
  var result = []; // 創(chuàng)建一個數(shù)組
  var i; // 聲明一個值,用來循環(huán)
  for (i = 0; i != a.length; i++)
    result[i] = f(a[i]);
      return result;
}
var f = function(x) {
   return x * x * x; 
}
var numbers = [0,1, 2, 5,10];
var cube = map(f,numbers);
console.log(cube);

返回 [0, 1, 8, 125, 1000]。

在 JavaScript 中,可以根據(jù)條件來定義一個函數(shù)。比如下面的代碼,當num 等于 0 的時候才會定義 myFunc :

var myFunc;
if (num == 0){
  myFunc = function(theObject) {
    theObject.make = "Toyota"
  }
}

除了上述的定義函數(shù)方法外,你也可以在運行時用 Function 構(gòu)造器由一個字符串來創(chuàng)建一個函數(shù) ,很像 eval() 函數(shù)。

當一個函數(shù)是一個對象的屬性時,稱之為方法。了解更多關(guān)于對象和方法的知識 使用對象。

調(diào)用函數(shù)

調(diào)用函數(shù)節(jié)
定義一個函數(shù)并不會自動的執(zhí)行它。定義了函數(shù)僅僅是賦予函數(shù)以名稱并明確函數(shù)被調(diào)用時該做些什么。調(diào)用函數(shù)才會以給定的參數(shù)真正執(zhí)行這些動作。例如,一旦你定義了函數(shù)square,你可以如下這樣調(diào)用它:

square(5);
上述語句通過提供參數(shù) 5 來調(diào)用函數(shù)。函數(shù)執(zhí)行完它的語句會返回值25。

函數(shù)一定要處于調(diào)用它們的域中,但是函數(shù)的聲明可以被提升(出現(xiàn)在調(diào)用語句之后),如下例:

console.log(square(5));
/* ... */
function square(n) { return n*n }

函數(shù)域是指函數(shù)聲明時的所在的地方,或者函數(shù)在頂層被聲明時指整個程序。

提示:注意只有使用如上的語法形式(即 function funcName(){})才可以。而下面的代碼是無效的。就是說,函數(shù)提升僅適用于函數(shù)聲明,而不適用于函數(shù)表達式。

console.log(square); // square is hoisted with an initial value undefined.
console.log(square(5)); // TypeError: square is not a function
var square = function (n) { 
  return n * n; 
}

函數(shù)的參數(shù)并不局限于字符串或數(shù)字。你也可以將整個對象傳遞給函數(shù)。函數(shù) show_props(其定義參見 用對象編程)就是一個將對象作為參數(shù)的例子。

函數(shù)可以被遞歸,就是說函數(shù)可以調(diào)用其本身。例如,下面這個函數(shù)就是用遞歸計算階乘:

function factorial(n){
  if ((n == 0) || (n == 1))
    return 1;
  else
    return (n * factorial(n - 1));
}

你可以計算1-5的階乘如下:

var a, b, c, d, e;

a = factorial(1); // 1賦值給a
b = factorial(2); // 2賦值給b
c = factorial(3); // 6賦值給c
d = factorial(4); // 24賦值給d
e = factorial(5); // 120賦值給e

還有其它的方式來調(diào)用函數(shù)。常見的一些情形是某些地方需要動態(tài)調(diào)用函數(shù),或者函數(shù)的實參數(shù)量是變化的,或者調(diào)用函數(shù)的上下文需要指定為在運行時確定的特定對象。顯然,函數(shù)本身就是對象,因此這些對象也有方法(參考Function )。作為此中情形之一,apply()方法可以實現(xiàn)這些目的。

函數(shù)作用域

在函數(shù)內(nèi)定義的變量不能在函數(shù)之外的任何地方訪問,因為變量僅僅在該函數(shù)的域的內(nèi)部有定義。相對應(yīng)的,一個函數(shù)可以訪問定義在其范圍內(nèi)的任何變量和函數(shù)。換言之,定義在全局域中的函數(shù)可以訪問所有定義在全局域中的變量。在另一個函數(shù)中定義的函數(shù)也可以訪問在其父函數(shù)中定義的所有變量和父函數(shù)有權(quán)訪問的任何其他變量。

// 下面的變量定義在全局作用域(global scope)中
var num1 = 20,
    num2 = 3,
    name = "Chamahk";

// 本函數(shù)定義在全局作用域
function multiply() {
  return num1 * num2;
}

multiply(); // 返回 60

// 嵌套函數(shù)的例子
function getScore() {
  var num1 = 2,
      num2 = 3;
  
  function add() {
    return name + " scored " + (num1 + num2);
  }
  
  return add();
}

getScore(); // 返回 "Chamahk scored 5"
作用域和函數(shù)堆棧 遞歸

一個函數(shù)可以指向并調(diào)用自身。有三種方法可以達到這個目的:

函數(shù)名

arguments.callee

作用域下的一個指向該函數(shù)的變量名

例如,思考一下如下的函數(shù)定義:

var foo = function bar() {
   // statements go here
};

在這個函數(shù)體內(nèi),以下的語句是等價的:

bar()

arguments.callee()

foo()

調(diào)用自身的函數(shù)我們稱之為遞歸函數(shù)。在某種意義上說,遞歸近似于循環(huán)。兩者都重復(fù)執(zhí)行相同的代碼,并且兩者都需要一個終止條件(避免無限循環(huán)或者無限遞歸)。例如以下的循環(huán):

var x = 0;
while (x < 10) { // "x < 10" 是循環(huán)條件
   // do stuff
   x++;
}

可以被轉(zhuǎn)化成一個遞歸函數(shù)和對其的調(diào)用:

function loop(x) {
  if (x >= 10) // "x >= 10" 是退出條件(等同于 "!(x < 10)")
    return;
  // 做些什么
  loop(x + 1); // 遞歸調(diào)用
}
loop(0);

不過,有些算法并不能簡單的用迭代來實現(xiàn)。例如,獲取樹結(jié)構(gòu)中所有的節(jié)點時,使用遞歸實現(xiàn)要容易得多:

function walkTree(node) {
  if (node == null) // 
    return;
  // do something with node
  for (var i = 0; i < node.childNodes.length; i++) {
    walkTree(node.childNodes[i]);
  }
}

跟loop函數(shù)相比,這里每個遞歸調(diào)用都產(chǎn)生了更多的遞歸。

將遞歸算法轉(zhuǎn)換為非遞歸算法是可能的,不過邏輯上通常會更加復(fù)雜,而且需要使用堆棧。事實上,遞歸函數(shù)就使用了堆棧:函數(shù)堆棧。

這種類似堆棧的行為可以在下例中看到:

function foo(i) {
  if (i < 0)
    return;
  console.log("begin:" + i);
  foo(i - 1);
  console.log("end:" + i);
}
foo(3);

// 輸出:

// begin:3
// begin:2
// begin:1
// begin:0
// end:0
// end:1
// end:2
// end:3
嵌套函數(shù)和閉包

你可以在一個函數(shù)里面嵌套另外一個函數(shù)。嵌套(內(nèi)部)函數(shù)對其容器(外部)函數(shù)是私有的。它自身也形成了一個閉包。一個閉包是一個可以自己擁有獨立的環(huán)境與變量的的表達式(通常是函數(shù))。

既然嵌套函數(shù)是一個閉包,就意味著一個嵌套函數(shù)可以”繼承“容器函數(shù)的參數(shù)和變量。換句話說,內(nèi)部函數(shù)包含外部函數(shù)的作用域。

可以總結(jié)如下:

內(nèi)部函數(shù)只可以在外部函數(shù)中訪問。

內(nèi)部函數(shù)形成了一個閉包:它可以訪問外部函數(shù)的參數(shù)和變量,但是外部函數(shù)卻不能使用它的參數(shù)和變量。

下面的例子展示了嵌套函數(shù):

function addSquares(a, b) {
  function square(x) {
    return x * x;
  }
  return square(a) + square(b);
}
a = addSquares(2, 3); // returns 13
b = addSquares(3, 4); // returns 25
c = addSquares(4, 5); // returns 41

由于內(nèi)部函數(shù)形成了閉包,因此你可以調(diào)用外部函數(shù)并為外部函數(shù)和內(nèi)部函數(shù)指定參數(shù):

function outside(x) {
  function inside(y) {
    return x + y;
  }
  return inside;
}
fn_inside = outside(3); // Think of it like: give me a function that adds 3 to whatever you give it
result = fn_inside(5); // returns 8

result1 = outside(3)(5); // returns 8
多層嵌套函數(shù)

函數(shù)可以被多層嵌套。例如,函數(shù)A可以包含函數(shù)B,函數(shù)B可以再包含函數(shù)C。B和C都形成了閉包,所以B可以訪問A,C可以訪問B和A。因此,閉包可以包含多個作用域;他們遞歸式的包含了所有包含它的函數(shù)作用域。這個稱之為作用域鏈。(稍后會詳細解釋)

思考一下下面的例子:

function A(x) {
  function B(y) {
    function C(z) {
      console.log(x + y + z);
    }
    C(3);
  }
  B(2);
}
A(1); // logs 6 (1 + 2 + 3)

在這個例子里面,C可以訪問B的y和A的x。這是因為:

B形成了一個包含A的閉包,B可以訪問A的參數(shù)和變量
C形成了一個包含B的閉包
B包含A,所以C也包含A,C可以訪問B和A的參數(shù)和變量。換言之,C用這個順序鏈接了B和A的作用域
反過來卻不是這樣。A不能訪問C,因為A看不到B中的參數(shù)和變量,C是B中的一個變量,所以C是B私有的。

命名沖突

當同一個閉包作用域下兩個參數(shù)或者變量同名時,就會產(chǎn)生命名沖突。更近的作用域有更高的優(yōu)先權(quán),所以最近的優(yōu)先級最高,最遠的優(yōu)先級最低。這就是作用域鏈。鏈的第一個元素就是最里面的作用域,最后一個元素便是最外層的作用域。

看以下的例子:

function outside() {
  var x = 5;
  function inside(x) {
    return x * 2;
  }
  return inside;
}

outside()(10); // returns 20 instead of 10
命名沖突發(fā)生在return x上,inside的參數(shù)x和outside變量x發(fā)生了沖突。這里的作用鏈域是{inside, outside, 全局對象}。因此inside的x具有最高優(yōu)先權(quán),返回了20(inside的x)而不是10(outside的x)。

閉包

閉包是 JavaScript 中最強大的特性之一。JavaScript 允許函數(shù)嵌套,并且內(nèi)部函數(shù)可以訪問定義在外部函數(shù)中的所有變量和函數(shù),以及外部函數(shù)能訪問的所有變量和函數(shù)。但是,外部函數(shù)卻不能夠訪問定義在內(nèi)部函數(shù)中的變量和函數(shù)。這給內(nèi)部函數(shù)的變量提供了一定的安全性。此外,由于內(nèi)部函數(shù)可以訪問外部函數(shù)的作用域,因此當內(nèi)部函數(shù)生存周期大于外部函數(shù)時,外部函數(shù)中定義的變量和函數(shù)將的生存周期比內(nèi)部函數(shù)執(zhí)行時間長。當內(nèi)部函數(shù)以某一種方式被任何一個外部函數(shù)作用域訪問時,一個閉包就產(chǎn)生了。

var pet = function(name) {          //外部函數(shù)定義了一個變量"name"
  var getName = function() {            
    //內(nèi)部函數(shù)可以訪問 外部函數(shù)定義的"name"
    return name; 
  }
  //返回這個內(nèi)部函數(shù),從而將其暴露在外部函數(shù)作用域
  return getName;               
};
myPet = pet("Vivie");
    
myPet();                            // 返回結(jié)果 "Vivie"

實際上可能會比上面的代碼復(fù)雜的多。在下面這種情形中,返回了一個包含可以操作外部函數(shù)的內(nèi)部變量方法的對象。

var createPet = function(name) {
  var sex;
  
  return {
    setName: function(newName) {
      name = newName;
    },
    
    getName: function() {
      return name;
    },
    
    getSex: function() {
      return sex;
    },
    
    setSex: function(newSex) {
      if(typeof newSex == "string" 
        && (newSex.toLowerCase() == "male" || newSex.toLowerCase() == "female")) {
        sex = newSex;
      }
    }
  }
}

var pet = createPet("Vivie");
pet.getName();                  // Vivie

pet.setName("Oliver");
pet.setSex("male");
pet.getSex();                   // male
pet.getName();                  // Oliver

在上面的代碼中,外部函數(shù)的name變量對內(nèi)嵌函數(shù)來說是可取得的,而除了通過內(nèi)嵌函數(shù)本身,沒有其它任何方法可以取得內(nèi)嵌的變量。內(nèi)嵌函數(shù)的內(nèi)嵌變量就像內(nèi)嵌函數(shù)的保險柜。它們會為內(nèi)嵌函數(shù)保留“穩(wěn)定”——而又安全——的數(shù)據(jù)參與運行。而這些內(nèi)嵌函數(shù)甚至不會被分配給一個變量,或者不必一定要有名字。

var getCode = (function(){
  var secureCode = "0]Eal(eh&2";    // A code we do not want outsiders to be able to modify...
  
  return function () {
    return secureCode;
  };
})();

getCode();    // Returns the secret code

盡管有上述優(yōu)點,使用閉包時仍然要小心避免一些陷阱。如果一個閉包的函數(shù)用外部函數(shù)的變量名定義了同樣的變量,那在外部函數(shù)域?qū)⒃僖矡o法指向該變量。

var createPet = function(name) {  // Outer function defines a variable called "name"
  return {
    setName: function(name) {    // Enclosed function also defines a variable called "name"
      name = name;               // ??? How do we access the "name" defined by the outer function ???
    }
  }
}
箭頭函數(shù) this 的詞法

在箭頭函數(shù)出現(xiàn)之前,每一個新函數(shù)都重新定義了自己的 this 值(在嚴格模式下,一個新的對象在構(gòu)造函數(shù)里是未定義的,以“對象方法”的方式調(diào)用的函數(shù)是上下文對象等)。以面向?qū)ο蟮木幊田L(fēng)格,這樣著實有點惱人。

function Person() {
  // The Person() constructor defines `this` as itself.
  this.age = 0;

  setInterval(function growUp() {
    // In nonstrict mode, the growUp() function defines `this` 
    // as the global object, which is different from the `this`
    // defined by the Person() constructor.
    this.age++;
  }, 1000);
}

var p = new Person();

在ECMAScript 3/5里,通過把this的值賦值給一個變量可以修復(fù)這個問題。

function Person() {
  var self = this; // Some choose `that` instead of `self`. 
                   // Choose one and be consistent.
  self.age = 0;

  setInterval(function growUp() {
    // The callback refers to the `self` variable of which
    // the value is the expected object.
    self.age++;
  }, 1000);
}

另外,創(chuàng)建一個約束函數(shù)可以使得 this值被正確傳遞給 growUp() 函數(shù)。

箭頭函數(shù)捕捉閉包上下文的this值,所以下面的代碼工作正常。

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();
預(yù)定義函數(shù)

JavaScript語言有好些個頂級的內(nèi)建函數(shù):

eval()

eval()方法會對一串字符串形式的JavaScript代碼字符求值。

uneval()

uneval()方法創(chuàng)建的一個Object的源代碼的字符串表示。

isFinite()

isFinite()函數(shù)判斷傳入的值是否是有限的數(shù)值。 如果需要的話,其參數(shù)首先被轉(zhuǎn)換為一個數(shù)值。

isNaN()

isNaN()函數(shù)判斷一個值是否是NaN。注意:isNaN函數(shù)內(nèi)部的強制轉(zhuǎn)換規(guī)則十分有趣; 另一個可供選擇的是ECMAScript 6 中定義Number.isNaN() , 或者使用 typeof來判斷數(shù)值類型。

parseFloat()

parseFloat() 函數(shù)解析字符串參數(shù),并返回一個浮點數(shù)。

parseInt()

parseInt() 函數(shù)解析字符串參數(shù),并返回指定的基數(shù)(基礎(chǔ)數(shù)學(xué)中的數(shù)制)的整數(shù)。

decodeURI()

decodeURI() 函數(shù)對先前經(jīng)過encodeURI函數(shù)或者其他類似方法編碼過的字符串進行解碼。

decodeURIComponent()

decodeURIComponent()方法對先前經(jīng)過encodeURIComponent函數(shù)或者其他類似方法編碼過的字符串進行解碼。

encodeURI()

encodeURI()方法通過用以一個,兩個,三個或四個轉(zhuǎn)義序列表示字符的UTF-8編碼替換統(tǒng)一資源標識符(URI)的某些字符來進行編碼(每個字符對應(yīng)四個轉(zhuǎn)義序列,這四個序列組了兩個”替代“字符)。

encodeURIComponent()

encodeURIComponent() 方法通過用以一個,兩個,三個或四個轉(zhuǎn)義序列表示字符的UTF-8編碼替換統(tǒng)一資源標識符(URI)的每個字符來進行編碼(每個字符對應(yīng)四個轉(zhuǎn)義序列,這四個序列組了兩個”替代“字符)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/110263.html

相關(guān)文章

  • 復(fù)習(xí)Javascript專題(二):閉包,內(nèi)存,以及垃圾回收機制

    摘要:一個閉包就是當一個函數(shù)返回時,一個沒有釋放資源的棧區(qū)所以參數(shù)和變量不會被垃圾回收機制回收。使用不當會很容易造成內(nèi)存泄露。最后,垃圾回收器完成內(nèi)存清除工作,銷毀那些帶標記的值并回收它們所占用的內(nèi)存空間。 1.什么是閉包?閉包有啥特性以及存在什么問題? 概念:閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。下面的outer就形成了一個閉包: function outer(){ co...

    hankkin 評論0 收藏0
  • 【重溫基礎(chǔ)】1.語法和數(shù)據(jù)類型

    摘要:語法和數(shù)據(jù)類型正文開始本章節(jié)復(fù)習(xí)的是中的基本語法,變量聲明,數(shù)據(jù)類型和字面量。聲明一個塊作用域的局部變量,可賦一個初始值。變量聲明有三種方式如,聲明局部變量和全局變量。 最近開始把精力放在重新復(fù)習(xí)JavaScript的基礎(chǔ)知識上面,不再太追求各種花枝招展的前端框架,框架再多,適合實際項目才是最重要。 上星期在掘金發(fā)布了幾篇文章,其中最大塊算是 【復(fù)習(xí)資料】ES6/ES7/ES8/ES...

    Darkgel 評論0 收藏0
  • 一次爬蟲實踐記錄

    摘要:在和偉鋒探討的時候,我突然想到了可以用爬蟲的手段,來將數(shù)據(jù)中心的數(shù)據(jù)全部爬取出來。這里做一個技術(shù)記錄,中間涉及到的知識點包括如何通過中的,以及維持登陸狀態(tài),以爬取不同的需要登陸以后才能查看的網(wǎng)頁。 前言說明: 公司在2017年3月的時候開發(fā)過一個「數(shù)據(jù)中心」,是將有贊的用戶和訂單信息通過API拉取到自己開發(fā)的網(wǎng)站上,再結(jié)合我們自己和用戶溝通的信息,組成一個簡單的用戶管理中心。數(shù)據(jù)中心雖...

    hzx 評論0 收藏0
  • 學(xué)不動了?可能方法不太對-Grid 網(wǎng)格布局

    摘要:前情提要本人是一個學(xué)渣非科班入行年了吧前端東西真的好多啊又不斷更新需要不斷的學(xué)學(xué)學(xué)在去年年底開始我就開始不斷的尋找學(xué)習(xí)的方法如何更加高效的學(xué)習(xí)如何才能學(xué)的又快又好在這半年來不斷的總結(jié)慢慢找到了一些方法和訣竅此文章不是網(wǎng)格布局的教學(xué)文章只前情提要 ??本人是一個學(xué)渣,非科班入行2年了吧,前端東西真的好多啊,又不斷更新.需要不斷的學(xué)學(xué)學(xué), showImg(https://user-gold-c...

    happyfish 評論0 收藏0

發(fā)表評論

0條評論

xuexiangjys

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<