成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript 編程精解 中文第三版 四、數(shù)據(jù)結(jié)構(gòu):對象和數(shù)組

kamushin233 / 3374人閱讀

摘要:本章將介紹基本的數(shù)據(jù)結(jié)構(gòu)。松鼠人一般在晚上八點(diǎn)到十點(diǎn)之間,雅克就會變身成為一只毛茸茸的松鼠,尾巴上的毛十分濃密。我們將雅克的日記表示為對象數(shù)組。

來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目

原文:Data Structures: Objects and Arrays

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

自豪地采用谷歌翻譯

部分參考了《JavaScript 編程精解(第 2 版)》

On two occasions I have been asked, ‘Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?’ [...] I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.

Charles Babbage,《Passages from the Life of a Philosopher》(1864)

數(shù)字,布爾和字符串是構(gòu)建數(shù)據(jù)結(jié)構(gòu)的原子。 不過,許多類型的信息都需要多個(gè)原子。 對象允許我們將值(包括其他對象)放到一起,來構(gòu)建更復(fù)雜的結(jié)構(gòu)。

我們迄今為止構(gòu)建的程序,受到一個(gè)事實(shí)的限制,它們僅在簡單數(shù)據(jù)類型上運(yùn)行。 本章將介紹基本的數(shù)據(jù)結(jié)構(gòu)。 到最后,你會知道足夠多的東西,開始編寫有用的程序。

本章將著手于一個(gè)或多或少的實(shí)際編程示例,當(dāng)概念適用于手頭問題時(shí)引入它們。 示例代碼通?;诒疚那懊娼榻B的函數(shù)和綁定。

松鼠人

一般在晚上八點(diǎn)到十點(diǎn)之間,雅克就會變身成為一只毛茸茸的松鼠,尾巴上的毛十分濃密。

一方面,雅克非常高興他沒有變成經(jīng)典的狼人。 與變成狼相比,變成松鼠的確會產(chǎn)生更少的問題。 他不必?fù)?dān)心偶然吃掉鄰居(那會很尷尬),而是擔(dān)心被鄰居的貓吃掉。 他在橡木樹冠上的一個(gè)薄薄的樹枝上醒來,赤身裸體并迷失方向。在這兩次偶然之后,他在晚上鎖上了房間的門窗,并在地板上放了幾個(gè)核桃,來使自己忙起來。

這就解決了貓和樹的問題。 但雅克寧愿完全擺脫他的狀況。 不規(guī)律發(fā)生的變身使他懷疑,它們可能會由某種東西觸發(fā)。 有一段時(shí)間,他相信只有在他靠近橡樹的日子里才會發(fā)生。 但是避開橡樹不能阻止這個(gè)問題。

雅克切換到了更科學(xué)的方法,開始每天記錄他在某一天所做的每件事,以及他是否變身。 有了這些數(shù)據(jù),他希望能夠縮小觸發(fā)變身的條件。

他需要的第一個(gè)東西,是存儲這些信息的數(shù)據(jù)結(jié)構(gòu)。

數(shù)據(jù)集

為了處理大量的數(shù)字?jǐn)?shù)據(jù),我們首先必須找到一種方法,將其在我們的機(jī)器內(nèi)存中表示。 舉例來說,我們想要表示一組數(shù)字 2, 3, 5, 7 和 11。

我們可以用字符串來創(chuàng)建 - 畢竟,字符串可以有任意長度,所以我們可以把大量數(shù)據(jù)放入它們中,并使用"2 3 5 7 11"作為我們的表示。 但這很笨拙。 你必須以某種方式提取數(shù)字,并將它們轉(zhuǎn)換回?cái)?shù)字才能訪問它們。

幸運(yùn)的是,JavaScript提供了一種數(shù)據(jù)類型,專門用于存儲一系列的值。我們將這種數(shù)據(jù)類型稱為數(shù)組,將一連串的值寫在方括號當(dāng)中,值之間使用逗號(,)分隔。

let listOfNumbers = [2, 3, 5, 7, 11];
console.log(listOfNumbers[2]);
// → 5
console.log(listOfNumbers[0]);
// → 2
console.log(listOfNumbers[2 - 1]);
// → 3

我們同樣使用方括號來獲取數(shù)組當(dāng)中的值。在表達(dá)式后緊跟一對方括號,并在方括號中填寫表達(dá)式,這將會在左側(cè)表達(dá)式里查找方括號中給定的索引所對應(yīng)的值,并返回結(jié)果。

數(shù)組的第一個(gè)索引是零,而不是一。 所以第一個(gè)元素用listOfNumbers[0]獲取。 基于零的計(jì)數(shù)在技術(shù)上有著悠久的傳統(tǒng),并且在某些方面意義很大,但需要一些時(shí)間來習(xí)慣。 將索引看作要跳過的項(xiàng)目數(shù)量,從數(shù)組的開頭計(jì)數(shù)。

屬性

在之前的章節(jié)中,我們已經(jīng)看到了一些可疑的表達(dá)式,例如myString.length(獲取字符串的長度)和Math.max(最大值函數(shù))。 這些表達(dá)式可以訪問某個(gè)值的屬性。 在第一個(gè)中,我們訪問myString中的length屬性。 第二個(gè)中,我們訪問Math對象(它是數(shù)學(xué)相關(guān)常量和函數(shù)的集合)中的名為max的屬性。

在 JavaScript 中,幾乎所有的值都有屬性。但nullundefined沒有。如果你嘗試訪問nullundefined的屬性,會得到一個(gè)錯誤提示。

null.length;
// → TypeError: null has no properties

在JavaScript中訪問屬性的兩種主要方式是點(diǎn)(.)和方括號([])。 value.xvalue [x]都可以訪問value屬性,但不一定是同一個(gè)屬性。 區(qū)別在于如何解釋x。 使用點(diǎn)時(shí),點(diǎn)后面的單詞是該屬性的字面名稱。 使用方括號時(shí),會求解括號內(nèi)的表達(dá)式來獲取屬性名稱。 鑒于value.x獲取value的名為x的屬性,value [x]嘗試求解表達(dá)式x,并將結(jié)果轉(zhuǎn)換為字符串作為屬性名稱。

所以如果你知道你感興趣的屬性叫做color,那么你會寫value.color。 如果你想提取屬性由綁定i中保存的值命名,你可以寫value [i]。 屬性名稱是字符串。 它們可以是任何字符串,但點(diǎn)符號僅適用于看起來像有效綁定名的名稱。 所以如果你想訪問名為2John Doe的屬性,你必須使用方括號:value[2]value["John Doe"]。

數(shù)組中的元素以數(shù)組屬性的形式存儲,使用數(shù)字作為屬性名稱。 因?yàn)槟悴荒苡命c(diǎn)號來表示數(shù)字,并且通常想要使用一個(gè)保存索引的綁定,所以你必須使用括號來表達(dá)它們。

數(shù)組的length屬性告訴我們它有多少個(gè)元素。 這個(gè)屬性名是一個(gè)有效的綁定名,我們事先知道它的名字,所以為了得到一個(gè)數(shù)組的長度,通常寫array.length,因?yàn)樗?b>array["length"]更容易編寫。

方法

length屬性之外,字符串和數(shù)組對象都包含一些持有函數(shù)值的屬性。

let doh = "Doh";
console.log(typeof doh.toUpperCase);
// → function
console.log(doh.toUpperCase());
// → DOH

每個(gè)字符串都有toUpperCase屬性。 調(diào)用時(shí),它將返回所有字母轉(zhuǎn)換為大寫字符串的副本。 另外還有toLowerCase。

有趣的是,雖然我們沒有在調(diào)用toUpperCase時(shí)傳遞任何參數(shù),但該函數(shù)訪問了字符串"Doh",即被調(diào)用的屬性所屬的值。我們會在第 6 章中闡述這其中的原理。

我們通常將包含函數(shù)的屬性稱為某個(gè)值的方法。比如說,toUpperCase是字符串的一個(gè)方法。

此示例演示了兩種方法,可用于操作數(shù)組:

let sequence = [1, 2, 3];
sequence.push(4);
sequence.push(5);
console.log(sequence);
// → [1, 2, 3, 4, 5]
console.log(sequence.pop());
// → 5
console.log(sequence);
// → [1, 2, 3, 4]

push方法將值添加到數(shù)組的末尾,而pop方法則相反,刪除數(shù)組中的最后一個(gè)值并將其返回。

這些有點(diǎn)愚蠢的名字是棧的傳統(tǒng)術(shù)語。 編程中的棧是一種數(shù)據(jù)結(jié)構(gòu),它允許你將值推入并按相反順序再次彈出,最后添加的內(nèi)容首先被移除。 這些在編程中很常見 - 你可能還記得前一章中的函數(shù)調(diào)用棧,它是同一個(gè)想法的實(shí)例。

對象

回到松鼠人的示例。 一組每日的日志條目可以表示為一個(gè)數(shù)組。 但是這些條目并不僅僅由一個(gè)數(shù)字或一個(gè)字符串組成 - 每個(gè)條目需要存儲一系列活動和一個(gè)布爾值,表明雅克是否變成了松鼠。 理想情況下,我們希望將它們組合成一個(gè)值,然后將這些分組的值放入日志條目的數(shù)組中。

對象類型的值是任意的屬性集合。 創(chuàng)建對象的一種方法是使用大括號作為表達(dá)式。

let day1 = {
  squirrel: false,
  events: ["work", "touched tree", "pizza", "running"]
};
console.log(day1.squirrel);
// → false
console.log(day1.wolf);
// → undefined
day1.wolf = false;
console.log(day1.wolf);
// → false

大括號內(nèi)有一列用逗號分隔的屬性。 每個(gè)屬性都有一個(gè)名字,后跟一個(gè)冒號和一個(gè)值。 當(dāng)一個(gè)對象寫為多行時(shí),像這個(gè)例子那樣,對它進(jìn)行縮進(jìn)有助于提高可讀性。 名稱不是有效綁定名稱或有效數(shù)字的屬性必須加引號。

let descriptions = {
  work: "Went to work",
  "touched tree": "Touched a tree"
};

這意味著大括號在 JavaScript 中有兩個(gè)含義。 在語句的開頭,他們起始了一個(gè)語句塊。 在任何其他位置,他們描述一個(gè)對象。 幸運(yùn)的是,語句很少以花括號對象開始,因此這兩者之間的不明確性并不是什么大問題。

讀取一個(gè)不存在的屬性就會產(chǎn)生undefined。

我們可以使用=運(yùn)算符來給一個(gè)屬性表達(dá)式賦值。如果該屬性已經(jīng)存在,那么這項(xiàng)操作就會替換原有的值。如果該屬性不存在,則會在目標(biāo)對象中新建一個(gè)屬性。

簡要回顧我們的綁定的觸手模型 - 屬性綁定也類似。 他們捕獲值,但其他綁定和屬性可能會持有這些相同的值。 你可以將對象想象成有任意數(shù)量觸手的章魚,每個(gè)觸手上都有一個(gè)名字的紋身。

delete運(yùn)算符切斷章魚的觸手。 這是一個(gè)一元運(yùn)算符,當(dāng)應(yīng)用于對象屬性時(shí),將從對象中刪除指定的屬性。 這不是一件常見的事情,但它是可能的。

let anObject = {left: 1, right: 2};
console.log(anObject.left);
// → 1
delete anObject.left;
console.log(anObject.left);
// → undefined
console.log("left" in anObject);
// → false
console.log("right" in anObject);
// → true

當(dāng)應(yīng)用于字符串和對象時(shí),二元in運(yùn)算符會告訴你該對象是否具有名稱為它的屬性。 將屬性設(shè)置為undefined,和實(shí)際刪除它的區(qū)別在于,在第一種情況下,對象仍然具有屬性(它只是沒有有意義的值),而在第二種情況下屬性不再存在,in會返回false。

為了找出對象具有的屬性,可以使用Object.keys函數(shù)。 你給它一個(gè)對象,它返回一個(gè)字符串?dāng)?shù)組 - 對象的屬性名稱。

console.log(Object.keys({x: 0, y: 0, z: 2}));
// → ["x", "y", "z"]

Object.assign函數(shù)可以將一個(gè)對象的所有屬性復(fù)制到另一個(gè)對象中。

let objectA = {a: 1, b: 2};
bject.assign(objectA, {b: 3, c: 4});
console.log(objectA);
// → {a: 1, b: 3, c: 4}

然后,數(shù)組只是一種對象,專門用于存儲對象序列。 如果你求解typeof [],它會產(chǎn)生object。 你可以看到它們是長而平坦的章魚,它們的觸手整齊排列,并以數(shù)字標(biāo)記。

我們將雅克的日記表示為對象數(shù)組。

let journal = [
  {events: ["work", "touched tree", "pizza",
            "running", "television"],
   squirrel: false},
  {events: ["work", "ice cream", "cauliflower",
            "lasagna", "touched tree", "brushed teeth"],
   squirrel: false},
  {events: ["weekend", "cycling", "break", "peanuts",
            "beer"],
   squirrel: true},
  /* and so on... */
];
可變性

我們現(xiàn)在即將開始真正的編程。 首先還有一個(gè)理論要理解。

我們看到對象值可以修改。 千米你的章節(jié)討論的值的類型(如數(shù)字,字符串和布爾值)都是不可變的 -- 這些類型的值不可能修改。 你可以將它們組合起來并從它們派生新的值,但是當(dāng)你采用特定的字符串值時(shí),該值將始終保持不變。 里面的文字不能改變。 如果你有一個(gè)包含"cat"的字符串,其他代碼不可能修改你的字符串中的一個(gè)字符,來使它變成"rat"

對象的工作方式不同。你可以更改其屬性,使單個(gè)對象值在不同時(shí)間具有不同的內(nèi)容。

當(dāng)我們有兩個(gè)數(shù)字,120 和 120 時(shí),我們可以將它們看作完全相同的數(shù)字,不管它們是否指向相同的物理位。 使用對象時(shí),擁有同一個(gè)對象的兩個(gè)引用,和擁有包含相同屬性的兩個(gè)不同的對象,是有區(qū)別的。 考慮下面的代碼:

let object1 = {value: 10};
let object2 = object1;
let object3 = {value: 10};

console.log(object1 == object2);
// → true
console.log(object1 == object3);
// → false

object1.value = 15;
console.log(object2.value);
// → 15
console.log(object3.value);
// → 10

object1object2綁定持有相同對象,這就是為什么改變object1會改變object2的值。 據(jù)說他們具有相同的身份。 綁定object3指向一個(gè)不同的對象,它最初包含的屬性與object1相同,但過著多帶帶的生活。

綁定可以是可變的或不變的,但這與它們的值的行為方式是分開的。 即使數(shù)值不變,你也可以使用let綁定來跟蹤一個(gè)變化的數(shù)字,通過修改綁定所指向的值。與之類似,雖然對象的const綁定本身不可改變,并且始終指向相同對象,該對象的內(nèi)容可能會改變。

const score = {visitors: 0, home: 0};
// This is okay
score.visitors = 1;
// This isn"t allowed
score = {visitors: 1, home: 1};

當(dāng)你用 JavaScript 的==運(yùn)算符比較對象時(shí),它按照身份進(jìn)行比較:僅當(dāng)兩個(gè)對象的值嚴(yán)格相同時(shí)才產(chǎn)生true。 比較不同的對象會返回false,即使它們屬性相同。 JavaScript 中沒有內(nèi)置的“深層”比較操作,它按照內(nèi)容比較對象,但可以自己編寫它(這是本章末尾的一個(gè)練習(xí))。

松鼠人的記錄

于是,雅克開始了他的 JavaScript 之旅,并搭建了用于保存每天記錄的一套開發(fā)環(huán)境。

let journal = [];

function addEntry(events, squirrel) {
  journal.push({events, squirrel});
}

請注意添加到日記中的對象看起來有點(diǎn)奇怪。 它不像events:events那樣聲明屬性,只是提供屬性名稱。 這是一個(gè)簡寫,意思一樣 - 如果大括號中的屬性名后面沒有值,它的值來自相同名稱的綁定。

那么,在每天晚上十點(diǎn) -- 或者有時(shí)候是下一天的早晨,從它的書架頂部爬下來之后 -- 雅克記錄了這一天。

addEntry(["work", "touched tree", "pizza", "running",
          "television"], false);
addEntry(["work", "ice cream", "cauliflower", "lasagna",
          "touched tree", "brushed teeth"], false);
addEntry(["weekend", "cycling", "break", "peanuts",
          "beer"], true);

一旦他有了足夠的數(shù)據(jù)點(diǎn),他打算使用統(tǒng)計(jì)學(xué)來找出哪些事件可能與變成松鼠有關(guān)。

關(guān)聯(lián)性是統(tǒng)計(jì)綁定之間的獨(dú)立性的度量。 統(tǒng)計(jì)綁定與編程綁定不完全相同。 在統(tǒng)計(jì)學(xué)中,你通常會有一組度量,并且每個(gè)綁定都根據(jù)每個(gè)度量來測量。 綁定之間的相關(guān)性通常表示為從 -1 到 1 的值。 相關(guān)性為零意味著綁定不相關(guān)。 相關(guān)性為一表明兩者完全相關(guān) - 如果你知道一個(gè),你也知道另一個(gè)。 負(fù)一意味著它們是完全相關(guān)的,但它們是相反的 - 當(dāng)一個(gè)是真的時(shí),另一個(gè)是假的。

為了計(jì)算兩個(gè)布爾綁定之間的相關(guān)性度量,我們可以使用 phi 系數(shù)(?)。 這是一個(gè)公式,輸入為一個(gè)頻率表格,包含觀測綁定的不同組合的次數(shù)。 公式的輸出是 -1 和 1 之間的數(shù)字。

我們可以將吃比薩的事件放在這樣的頻率表中,每個(gè)數(shù)字表示我們的度量中的組合的出現(xiàn)次數(shù)。

如果我們將那個(gè)表格稱為n,我們可以用下列公式自己算?

(如果你現(xiàn)在把這本書放下,專注于十年級數(shù)學(xué)課的可怕的再現(xiàn),堅(jiān)持??!我不打算用無休止的神秘符號折磨你 - 現(xiàn)在只有這一個(gè)公式。我們所做的就是把它變成 JavaScript。)

符號n01表明, 第一個(gè)綁定(松鼠)為假(0)時(shí),第二個(gè)綁定(披薩)為真(1)。 在披薩表中,n01是 9。

n1表示所有度量之和,其中第一個(gè)綁定為true,在示例表中為 5。 同樣,n0表示所有度量之和,其中第二個(gè)綁定為假。

因此,我們以比薩表為例,除法線上方的部分(被除數(shù))為1×76–9×4=40,而除法線下面的部分(除數(shù))則是10×80×5×85的平方根,也就是√340000。計(jì)算結(jié)果為?≈0.069,這個(gè)結(jié)果很小,因此吃比薩對是否變身成松鼠顯然沒有太大影響。

計(jì)算關(guān)聯(lián)性

我們可以用包含 4 個(gè)元素的數(shù)組([76,9,4,1])來表示一張 2 乘 2 的表格。我們也可以使用其他表示方式,比如包含兩個(gè)數(shù)組的數(shù)組,每個(gè)子數(shù)組又包含兩個(gè)元素([[76,9],[4,1]])。也可以使用一個(gè)對象,它包含一些屬性,名為"11""01"。但是,一維數(shù)組更為簡單,也容易進(jìn)行操作。我們可以將數(shù)組索引看成包含兩個(gè)二進(jìn)制位的數(shù)字,左邊的(高位)數(shù)字表示綁定“是否變成松鼠”,右邊的(低位)數(shù)字表示事件綁定。例如,若二進(jìn)制數(shù)字為 10,表示雅克變成了松鼠,但事件并未發(fā)生(比如說吃比薩)。這種情況發(fā)生了 4 次。由于二進(jìn)制數(shù)字 10 的十進(jìn)制是 2,因此我們將其存儲到數(shù)組中索引為 2 的位置上。

下面這個(gè)函數(shù)用于計(jì)算數(shù)組的系數(shù)?

function phi(table) {
  return (table[3] * table[0] - table[2] * table[1]) /
    Math.sqrt((table[2] + table[3]) *
              (table[0] + table[1]) *
              (table[1] + table[3]) *
              (table[0] + table[2]));
}

console.log(phi([76, 9, 4, 1]));
// → 0.068599434

這將?公式直接翻譯成 JavaScript。 Math.sqrt是平方根函數(shù),由標(biāo)準(zhǔn) JavaScript 環(huán)境中的Math對象提供。 我們必須在表格中添加兩個(gè)字段來獲取字段,例如n1因?yàn)樾泻突蛘吡泻筒恢苯哟鎯υ谖覀兊臄?shù)據(jù)結(jié)構(gòu)中。

雅克花了三個(gè)月的時(shí)間記錄日志。在本章的代碼沙箱(http://eloquentjavascript.net/code/)的下載文件中,用JOURNAL綁定存儲了該結(jié)果數(shù)據(jù)集合。

若要從這篇記錄中提取出某個(gè)特定事件的 2 乘 2 表格,我們首先需要循環(huán)遍歷整個(gè)記錄,并計(jì)算出與變身成松鼠相關(guān)事件發(fā)生的次數(shù)。

function hasEvent(event, entry) {
  return entry.events.indexOf(event) != -1;
}

function tableFor(event, journal) {
  let table = [0, 0, 0, 0];
  for (let i = 0; i < journal.length; i++) {
    let entry = journal[i], index = 0;
    if (entry.events.includes(event)) index += 1;
    if (entry.squirrel) index += 2;
    table[index] += 1;
  }
  return table;
}

console.log(tableFor("pizza", JOURNAL));
// → [76, 9, 4, 1]

數(shù)組擁有includes方法,檢查給定值是否存在于數(shù)組中。 該函數(shù)使用它來確定,對于某一天,感興趣的事件名稱是否在事件列表中。

tableFor中的循環(huán)體通過檢查列表是否包含它感興趣的特定事件,以及該事件是否與松鼠事件一起發(fā)生,來計(jì)算每個(gè)日記條目在表格中的哪個(gè)盒子。 然后循環(huán)對表中的正確盒子加一。

我們現(xiàn)在有了我們計(jì)算個(gè)體相關(guān)性的所需工具。 剩下的唯一一步,就是為記錄的每種類型的事件找到關(guān)聯(lián),看看是否有什么明顯之處。

數(shù)組循環(huán)

tableFor函數(shù)中,有一個(gè)這樣的循環(huán):

for (let i = 0; i < JOURNAL.length; i++) {
  let entry = JOURNAL[i];
  // Do something with entry
}

這種循環(huán)在經(jīng)典的 JavaScript 中很常見 - 遍歷數(shù)組,一次一個(gè)元素會很常見,為此,你需要在數(shù)組長度上維護(hù)一個(gè)計(jì)數(shù)器,并依次選取每個(gè)元素。

在現(xiàn)代 JavaScript 中有一個(gè)更簡單的方法來編寫這樣的循環(huán)。

for (let entry of JOURNAL) {
  console.log(`${entry.events.length} events.`);
}

當(dāng)for循環(huán)看起來像這樣,在綁定定義之后用of這個(gè)詞時(shí),它會遍歷of之后的給定值的元素。 這不僅適用于數(shù)組,而且適用于字符串和其他數(shù)據(jù)結(jié)構(gòu)。 我們將在第 6 章中討論它的工作原理。

分析結(jié)果

我們需要計(jì)算數(shù)據(jù)集中發(fā)生的每種類型事件的相關(guān)性。 為此,我們首先需要尋找每種類型的事件。

function journalEvents(journal) {
  let events = [];
  for (let entry of journal) {
    for (let event of entry.events) {
      if (!events.includes(event)) {
        events.push(event);
      }
    }
  }
  return events;
}

console.log(journalEvents(JOURNAL));
// → ["carrot", "exercise", "weekend", "bread", …]

通過遍歷所有事件,并將那些不在里面的事件添加到events數(shù)組中,該函數(shù)收集每種事件。

使用它,我們可以看到所有的相關(guān)性。

for (let event of journalEvents(JOURNAL)) {
  console.log(event + ":", phi(tableFor(event, JOURNAL)));
}
// → carrot:   0.0140970969
// → exercise: 0.0685994341
// → weekend:  0.1371988681
// → bread:   -0.0757554019
// → pudding: -0.0648203724
// and so on...

絕大多數(shù)相關(guān)系數(shù)都趨近于 0。顯然,攝入胡蘿卜、面包或布丁并不會導(dǎo)致變身成松鼠。但是似乎在周末變身成松鼠的概率更高。讓我們過濾結(jié)果,來僅僅顯示大于 0.1 或小于 -0.1 的相關(guān)性。

for (let event of journalEvents(JOURNAL)) {
  let correlation = phi(tableFor(event, JOURNAL));
  if (correlation > 0.1 || correlation < -0.1) {
    console.log(event + ":", correlation);
  }
}
// → weekend:        0.1371988681
// → brushed teeth: -0.3805211953
// → candy:          0.1296407447
// → work:          -0.1371988681
// → spaghetti:      0.2425356250
// → reading:        0.1106828054
// → peanuts:        0.5902679812

啊哈!這里有兩個(gè)因素,其相關(guān)性明顯強(qiáng)于其他因素。 吃花生對變成松鼠的幾率有強(qiáng)烈的積極影響,而刷牙有顯著的負(fù)面影響。

這太有意思了。讓我們再仔細(xì)看看這些數(shù)據(jù)。

for (let entry of JOURNAL) {
  if (entry.events.includes("peanuts") &&
     !entry.events.includes("brushed teeth")) {
     entry.events.push("peanut teeth");
  }
}
console.log(phi(tableFor("peanut teeth", JOURNAL)));
// → 1

這是一個(gè)強(qiáng)有力的結(jié)果。 這種現(xiàn)象正好發(fā)生在雅克吃花生并且沒有刷牙時(shí)。 如果他只是不注意口腔衛(wèi)生,他從來沒有注意到他的病痛。

知道這些之后,雅克完全停止吃花生,發(fā)現(xiàn)他的變身消失了。

幾年來,雅克過得越來越好。 但是在某個(gè)時(shí)候他失去了工作。 因?yàn)樗钤谝粋€(gè)糟糕的國家,沒有工作就意味著沒有醫(yī)療服務(wù),所以他被迫在一個(gè)馬戲團(tuán)就業(yè),在那里他扮演的是不可思議的松鼠人,在每場演出前都用花生醬塞滿了它的嘴。

數(shù)組詳解

在完成本章之前,我想向你介紹幾個(gè)對象相關(guān)的概念。 我將首先介紹一些通常實(shí)用的數(shù)組方法。

我們在本章的前面已經(jīng)了解了pushpop方法,分別用于在數(shù)組末尾添加或刪除元素。相應(yīng)地,在數(shù)組的開頭添加或刪除元素的方法分別是unshiftshift

let todoList = [];
function remember(task) {
  todoList.push(task);
}
function getTask() {
  return todoList.shift();
}
function rememberUrgently(task) {
  todoList.unshift(task);
}

這個(gè)程序管理任務(wù)隊(duì)列。 你通過調(diào)用remember("groceries"),將任務(wù)添加到隊(duì)列的末尾,并且當(dāng)你準(zhǔn)備好執(zhí)行某些操作時(shí),可以調(diào)用getTask()從隊(duì)列中獲?。úh除)第一個(gè)項(xiàng)目。 rememberUrgently函數(shù)也添加任務(wù),但將其添加到隊(duì)列的前面而不是隊(duì)列的后面。

有一個(gè)與indexOf方法類似的方法,叫lastIndexOf,只不過indexOf從數(shù)組第一個(gè)元素向后搜索,而lastIndexOf從最后一個(gè)元素向前搜索。

console.log([1, 2, 3, 2, 1].indexOf(2));
// → 1
console.log([1, 2, 3, 2, 1].lastIndexOf(2));
// → 3

indexOflastIndexOf方法都有一個(gè)可選參數(shù),可以用來指定搜索的起始位置。

另一個(gè)基本方法是slice,該方法接受一個(gè)起始索引和一個(gè)結(jié)束索引,然后返回?cái)?shù)組中兩個(gè)索引范圍內(nèi)的元素。起始索引元素包含在返回結(jié)果中,但結(jié)束索引元素不會包含在返回結(jié)果中。

console.log([0, 1, 2, 3, 4].slice(2, 4));
// → [2, 3]
console.log([0, 1, 2, 3, 4].slice(2));
// → [2, 3, 4]

如果沒有指定結(jié)束索引,slice會返回從起始位置之后的所有元素。你也可以省略起始索引來復(fù)制整個(gè)數(shù)組。

concat方法可用于將數(shù)組粘在一起,來創(chuàng)建一個(gè)新數(shù)組,類似于+運(yùn)算符對字符串所做的操作。

以下示例展示了concatslice的作用。 它接受一個(gè)數(shù)組和一個(gè)索引,然后它返回一個(gè)新數(shù)組,該數(shù)組是原數(shù)組的副本,并且刪除了給定索引處的元素:

function remove(array, index) {
  return array.slice(0, index)
    .concat(array.slice(index + 1));
}
console.log(remove(["a", "b", "c", "d", "e"], 2));
// → ["a", "b", "d", "e"]

如果你將concat傳遞給一個(gè)不是數(shù)組的參數(shù),該值將被添加到新數(shù)組中,就像它是單個(gè)元素的數(shù)組一樣。

字符串及其屬性

我們可以調(diào)用字符串的lengthtoUpperCase這樣的屬性,但不能向字符串中添加任何新的屬性。

let kim = "Kim";
kim.age = 88;
console.log(kim.age);
// → undefined

字符串、數(shù)字和布爾類型的值并不是對象,因此當(dāng)你向這些值中添加屬性時(shí) JavaScript 并不會報(bào)錯,但實(shí)際上你并沒有將這些屬性添加進(jìn)去。前面說過,這些值是不變的,不能改變。

但這些類型包含一些內(nèi)置屬性。每個(gè)字符串中包含了若干方法供我們使用,最有用的方法可能就是sliceindexOf了,它們的功能與數(shù)組中的同名方法類似。

console.log("coconuts".slice(4, 7));
// → nut
console.log("coconut".indexOf("u"));
// → 5

一個(gè)區(qū)別是,字符串的indexOf可以搜索包含多個(gè)字符的字符串,而相應(yīng)的數(shù)組方法僅查找單個(gè)元素。

console.log("one two three".indexOf("ee"));
// → 11

trim方法用于刪除字符串中開頭和結(jié)尾的空白符號(空格、換行符和制表符等符號)。

console.log("  okay 
 ".trim());
// → okay

上一章中的zeroPad函數(shù)也作為方法存在。 它被稱為padStart,接受所需的長度和填充字符作為參數(shù)。

console.log(String(6).padStart(3, "0"));
// → 006

你可以使用split,在另一個(gè)字符串的每個(gè)出現(xiàn)位置分割一個(gè)字符串,然后再用join把它連接在一起。

let sentence = "Secretarybirds specialize in stomping";
let words = sentence.split(" ");
console.log(words);
// → ["Secretarybirds", "specialize", "in", "stomping"]
console.log(words.join(". "));
// → Secretarybirds. specialize. in. stomping

可以用repeat方法重復(fù)一個(gè)字符串,該方法創(chuàng)建一個(gè)新字符串,包含原始字符串的多個(gè)副本,并將其粘在一起。

console.log("LA".repeat(3));
// → LALALA

我們已經(jīng)看到了字符串類型的length屬性。 訪問字符串中的單個(gè)字符,看起來像訪問數(shù)組元素(有一個(gè)警告,我們將在第 5 章中討論)。

let string = "abc";
console.log(string.length);
// → 3
console.log(string[1]);
// → b
剩余參數(shù)

一個(gè)函數(shù)可以接受任意數(shù)量的參數(shù)。 例如,Math.max計(jì)算提供給它的參數(shù)的最大值。

為了編寫這樣一個(gè)函數(shù),你需要在函數(shù)的最后一個(gè)參數(shù)之前放三個(gè)點(diǎn),如下所示:

function max(...numbers) {
  let result = -Infinity;
  for (let number of numbers) {
    if (number > result) result = number;
  }
  return result;
}
console.log(max(4, 1, 9, -2));
// → 9

當(dāng)這樣的函數(shù)被調(diào)用時(shí),剩余參數(shù)綁定一個(gè)數(shù)組,包含所有其它參數(shù)。 如果之前有其他參數(shù),它們的值不是該數(shù)組的一部分。 當(dāng)它是唯一的參數(shù)時(shí),如max中那樣,它將保存所有參數(shù)。

你可以使用類似的三點(diǎn)表示法,來使用參數(shù)數(shù)組調(diào)用函數(shù)。

let numbers = [5, 1, 7];
console.log(max(...numbers));
// → 7

這在函數(shù)調(diào)用中“展開”數(shù)組,并將其元素傳遞為多帶帶的參數(shù)。 像`max(9, ...numbers, 2)"那樣,可以包含像這樣的數(shù)組以及其他參數(shù)。

方括號的數(shù)組表示法,同樣允許三點(diǎn)運(yùn)算符將另一個(gè)數(shù)組展開到新數(shù)組中:

let words = ["never", "fully"];
console.log(["will", ...words, "understand"]);
// → ["will", "never", "fully", "understand"]
Math對象

正如我們所看到的那樣,Math對象中包含了許多與數(shù)字相關(guān)的工具函數(shù),比如Math.max(求最大值)、Math.min(求最小值)和Math.sqrt(求平方根)。

Math對象被用作一個(gè)容器來分組一堆相關(guān)的功能。 只有一個(gè)Math對象,它作為一個(gè)值幾乎沒有用處。 相反,它提供了一個(gè)命名空間,使所有這些函數(shù)和值不必是全局綁定。

過多的全局綁定會“污染”命名空間。全局綁定越多,就越有可能一不小心把某些綁定的值覆蓋掉。比如,我們可能想在程序中使用名為max的綁定,由于 JavaScript 將內(nèi)置的max函數(shù)安全地放置在Math對象中,因此不必?fù)?dān)心max的值會被覆蓋。

當(dāng)你去定義一個(gè)已經(jīng)被使用的綁定名的時(shí)候,對于很多編程語言來說,都會阻止你這么做,至少會對這種行為發(fā)出警告。但是 JavaScript 不會,因此要小心這些陷阱。

讓我們來繼續(xù)了解Math對象。如果需要做三角運(yùn)算,Math對象可以幫助到你,它包含cos(余弦)、sin(正弦)、tan(正切)和各自的反函數(shù)(acos、asinatan)。Math.PI則表示數(shù)字π,或至少是 JavaScript 中的數(shù)字近似值。在傳統(tǒng)的程序設(shè)計(jì)當(dāng)中,常量均以大寫來標(biāo)注。

function randomPointOnCircle(radius) {
  let angle = Math.random() * 2 * Math.PI;
  return {x: radius * Math.cos(angle),
          y: radius * Math.sin(angle)};
}
console.log(randomPointOnCircle(2));
// → {x: 0.3667, y: 1.966}

如果你對正弦或余弦不大熟悉,不必?fù)?dān)心。我們會在第 13 章用到它們時(shí),再做進(jìn)一步解釋。

在上面的示例代碼中使用了Math.random。每次調(diào)用該函數(shù)時(shí),會返回一個(gè)偽隨機(jī)數(shù),范圍在 0(包括)到 1(不包括)之間。

console.log(Math.random());
// → 0.36993729369714856
console.log(Math.random());
// → 0.727367032552138
console.log(Math.random());
// → 0.40180766698904335

雖然計(jì)算機(jī)是確定性的機(jī)器,但如果給定相同的輸入,它們總是以相同的方式作出反應(yīng) - 讓它們產(chǎn)生隨機(jī)顯示的數(shù)字是可能的。 為此,機(jī)器會維護(hù)一些隱藏的值,并且每當(dāng)你請求一個(gè)新的隨機(jī)數(shù)時(shí),它都會對該隱藏值執(zhí)行復(fù)雜的計(jì)算來創(chuàng)建一個(gè)新值。 它存儲一個(gè)新值并返回從中派生的一些數(shù)字。 這樣,它可以以隨機(jī)的方式產(chǎn)生新的,難以預(yù)測的數(shù)字。

如果我們想獲取一個(gè)隨機(jī)的整數(shù)而非小數(shù),可以使用Math.floor(向下取整到與當(dāng)前數(shù)字最接近的整數(shù))來處理Math.random的結(jié)果。

console.log(Math.floor(Math.random() * 10));
// → 2

將隨機(jī)數(shù)乘以 10 可以得到一個(gè)在 0 到 10 之間的數(shù)字。由于Math.floor是向下取整,因此該函數(shù)會等概率地取到 0 到 9 中的任何一個(gè)數(shù)字。

還有兩個(gè)函數(shù),分別是Math.ceil(向上取整)和Math.round(四舍五入)。以及Math.abs,它取數(shù)字的絕對值,這意味著它反轉(zhuǎn)了負(fù)值,但保留了正值。

解構(gòu)

讓我們暫時(shí)回顧phi函數(shù):

function phi(table) {
  return (table[3] * table[0] - table[2] * table[1]) /
    Math.sqrt((table[2] + table[3]) *
              (table[0] + table[1]) *
              (table[1] + table[3]) *
              (table[0] + table[2]));
}

這個(gè)函數(shù)難以閱讀的原因之一,是我們有一個(gè)指向數(shù)組的綁定,但我們更愿意擁有數(shù)組的元素的綁定,即let n00 = table [0]以及其他。 幸運(yùn)的是,有一種簡潔的方法可以在 JavaScript 中執(zhí)行此操作。

function phi([n00, n01, n10, n11]) {
  return (n11 * n00 - n10 * n01) /
    Math.sqrt((n10 + n11) * (n00 + n01) *
              (n01 + n11) * (n00 + n10));
}

這也適用于由let,varconst創(chuàng)建的綁定。 如果你知道要綁定的值是一個(gè)數(shù)組,則可以使用方括號來“向內(nèi)查看”該值,并綁定其內(nèi)容。

類似的技巧適用于對象,使用大括號代替方括號。

let {name} = {name: "Faraji", age: 23};
console.log(name);
// → Faraji

請注意,如果嘗試解構(gòu)nullundefined,則會出現(xiàn)錯誤,就像直接嘗試訪問這些值的屬性一樣。

JSON

因?yàn)閷傩灾皇遣东@了它們的值,而不是包含它們,對象和數(shù)組在計(jì)算機(jī)的內(nèi)存中儲存為字節(jié)序列,存放它們的內(nèi)容的地址(內(nèi)存中的位置)。 因此,包含另一個(gè)數(shù)組的數(shù)組,(至少)由兩個(gè)內(nèi)存區(qū)域組成,一個(gè)用于內(nèi)部數(shù)組,另一個(gè)用于外部數(shù)組,(除了其它東西之外)其中包含表示內(nèi)部數(shù)組位置的二進(jìn)制數(shù)。

如果你想稍后將數(shù)據(jù)保存到文件中,或者通過網(wǎng)絡(luò)將其發(fā)送到另一臺計(jì)算機(jī),則必須以某種方式,將這些內(nèi)存地址的線團(tuán)轉(zhuǎn)換為可以存儲或發(fā)送的描述。 我想你應(yīng)該把你的整個(gè)計(jì)算機(jī)內(nèi)存,連同你感興趣的值的地址一起發(fā)送,但這似乎并不是最好的方法。

我們可以做的是序列化數(shù)據(jù)。 這意味著它被轉(zhuǎn)換為扁平的描述。 流行的序列化格式稱為 JSON(發(fā)音為“Jason”),它代表 JavaScript Object Notation(JavaScript 對象表示法)。 它被廣泛用作 Web 上的數(shù)據(jù)存儲和通信格式,即使在 JavaScript 以外的語言中也是如此。

JSON 看起來像 JavaScript 的數(shù)組和對象的表示方式,但有一些限制。 所有屬性名都必須用雙引號括起來,并且只允許使用簡單的數(shù)據(jù)表達(dá)式 - 沒有函數(shù)調(diào)用,綁定或任何涉及實(shí)際計(jì)算的內(nèi)容。 JSON 中不允許注釋。

表示為 JSON 數(shù)據(jù)時(shí),日記條目可能看起來像這樣

{
  "squirrel": false,
  "events": ["work", "touched tree", "pizza", "running"]
}

JavaScript 為我們提供了函數(shù)JSON.stringifyJSON.parse,來將數(shù)據(jù)轉(zhuǎn)換為這種格式,以及從這種格式轉(zhuǎn)換。 第一個(gè)函數(shù)接受 JavaScript 值并返回 JSON 編碼的字符串。 第二個(gè)函數(shù)接受這樣的字符串并將其轉(zhuǎn)換為它編碼的值。

let string = JSON.stringify({squirrel: false,
                             events: ["weekend"]});
console.log(string);
// → {"squirrel":false,"events":["weekend"]}
console.log(JSON.parse(string).events);
// → ["weekend"]
本章小結(jié)

對象和數(shù)組(一種特殊對象)可以將幾個(gè)值組合起來形成一個(gè)新的值。理論上說,我們可以將一組相關(guān)的元素打包成一個(gè)對象,并通過這個(gè)對象來訪問這些元素,以避免管理那些支離破碎的元素。

在 JavaScript 中,除了nullundefined以外,絕大多數(shù)的值都含有屬性。我們可以用value.propvalue["prop"]來訪問屬性。對象使用名稱來定義和存儲一定數(shù)量的屬性。另外,數(shù)組中通常會包含不同數(shù)量的值,并使用數(shù)字(從 0 開始)作為這些值的屬性。

在數(shù)組中有一些具名屬性,比如length和一些方法。方法是作為屬性存在的函數(shù),常常作用于其所屬的值。

你可以使用特殊類型的for循環(huán)for (let element of array)來迭代數(shù)組。

習(xí)題 范圍的和

在本書的前言中,提到過一種很好的計(jì)算固定范圍內(nèi)數(shù)字之和的方法:

console.log(sum(range(1, 10)));

編寫一個(gè)range函數(shù),接受兩個(gè)參數(shù):startend,然后返回包含startend(包括end)之間的所有數(shù)字。

接著,編寫一個(gè)sum函數(shù),接受一個(gè)數(shù)字?jǐn)?shù)組,并返回所有數(shù)字之和。運(yùn)行示例程序,檢查一下結(jié)果是不是 55。

附加題是修改range函數(shù),接受第 3 個(gè)可選參數(shù),指定構(gòu)建數(shù)組時(shí)的步長(step)。如果沒有指定步長,構(gòu)建數(shù)組時(shí),每步增長 1,和舊函數(shù)行為一致。調(diào)用函數(shù)range(1, 10, 2),應(yīng)該返回[1, 3, 5, 7, 9]。另外確保步數(shù)值為負(fù)數(shù)時(shí)也可以正常工作,因此range(5, 2, -1)應(yīng)該產(chǎn)生[5, 4, 3, 2]。

// Your code here.

console.log(range(1, 10));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(5, 2, -1));
// → [5, 4, 3, 2]
console.log(sum(range(1, 10)));
// → 55
逆轉(zhuǎn)數(shù)組

數(shù)組有一個(gè)reverse方法,它可以逆轉(zhuǎn)數(shù)組中元素的次序。在本題中,編寫兩個(gè)函數(shù),reverseArrayreverseArrayInPlace。第一個(gè)函數(shù)reverseArray接受一個(gè)數(shù)組作為參數(shù),返回一個(gè)新數(shù)組,并逆轉(zhuǎn)新數(shù)組中的元素次序。第二個(gè)函數(shù)reverseArrayInPlace與第一個(gè)函數(shù)的功能相同,但是直接將數(shù)組作為參數(shù)進(jìn)行修改來,逆轉(zhuǎn)數(shù)組中的元素次序。兩者都不能使用標(biāo)準(zhǔn)的reverse方法。

回想一下,在上一章中關(guān)于副作用和純函數(shù)的討論,哪個(gè)函數(shù)的寫法的應(yīng)用場景更廣?哪個(gè)執(zhí)行得更快?

// Your code here.

console.log(reverseArray(["A", "B", "C"]));
// → ["C", "B", "A"];
let arrayValue = [1, 2, 3, 4, 5];
reverseArrayInPlace(arrayValue);
console.log(arrayValue);
// → [5, 4, 3, 2, 1]
實(shí)現(xiàn)列表

對象作為一個(gè)值的容器,它可以用來構(gòu)建各種各樣的數(shù)據(jù)結(jié)構(gòu)。有一種通用的數(shù)據(jù)結(jié)構(gòu)叫作列表(list)(不要與數(shù)組混淆)。列表是一種嵌套對象集合,第一個(gè)對象擁有第二個(gè)對象的引用,而第二個(gè)對象有第三個(gè)對象的引用,依此類推。

let list = {
  value: 1,
  rest: {
    value: 2,
    rest: {
      value: 3,
      rest: null
    }
  }
};

最后產(chǎn)生的對象形成了一條鏈,如下圖所示:

使用列表的一個(gè)好處是,它們之間可以共享相同的子列表。舉個(gè)例子,如果我們新建了兩個(gè)值:{value: 0,result: list}{value: -1,result: list}(list引用了我們前面定義的綁定)。這是兩個(gè)獨(dú)立的列表,但它們之間卻共享了同一個(gè)數(shù)據(jù)結(jié)構(gòu),該數(shù)據(jù)結(jié)構(gòu)包含列表末尾的三個(gè)元素。而且我們前面定義的list仍然是包含三個(gè)元素的列表。

編寫一個(gè)函數(shù)arrayToList,當(dāng)給定參數(shù)[1, 2, 3]時(shí),建立一個(gè)和示例相似的數(shù)據(jù)結(jié)構(gòu)。然后編寫一個(gè)listToArray函數(shù),將列表轉(zhuǎn)換成數(shù)組。再編寫一個(gè)工具函數(shù)prepend,接受一個(gè)元素和一個(gè)列表,然后創(chuàng)建一個(gè)新的列表,將元素添加到輸入列表的開頭。最后編寫一個(gè)函數(shù)nth,接受一個(gè)列表和一個(gè)數(shù),并返回列表中指定位置的元素,如果該元素不存在則返回undefined

如果你覺得這都不是什么難題,那么編寫一個(gè)遞歸版本的nth函數(shù)。

// Your code here.

console.log(arrayToList([10, 20]));
// → {value: 10, rest: {value: 20, rest: null}}
console.log(listToArray(arrayToList([10, 20, 30])));
// → [10, 20, 30]
console.log(prepend(10, prepend(20, null)));
// → {value: 10, rest: {value: 20, rest: null}}
console.log(nth(arrayToList([10, 20, 30]), 1));
// → 20
深層比較

==運(yùn)算符可以判斷對象是否相等。但有些時(shí)候,你希望比較的是對象中實(shí)際屬性的值。

編寫一個(gè)函數(shù)deepEqual,接受兩個(gè)參數(shù),若兩個(gè)對象是同一個(gè)值或兩個(gè)對象中有相同屬性,且使用deepEqual比較屬性值均返回true時(shí),返回true。

為了弄清楚通過身份(使用===運(yùn)算符)還是其屬性比較兩個(gè)值,可以使用typeof運(yùn)算符。如果對兩個(gè)值使用typeof均返回"object",則說明你應(yīng)該進(jìn)行深層比較。但需要考慮一個(gè)例外的情況:由于歷史原因,typeof null也會返回"object"。

當(dāng)你需要查看對象的屬性來進(jìn)行比較時(shí),Object.keys函數(shù)將非常有用。

// Your code here.

let obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105025.html

相關(guān)文章

  • JavaScript 編程精解 中文三版 十九、項(xiàng)目:像素藝術(shù)編輯器

    摘要:相反,當(dāng)響應(yīng)指針事件時(shí),它會調(diào)用創(chuàng)建它的代碼提供的回調(diào)函數(shù),該函數(shù)將處理應(yīng)用的特定部分?;卣{(diào)函數(shù)可能會返回另一個(gè)回調(diào)函數(shù),以便在按下按鈕并且將指針移動到另一個(gè)像素時(shí)得到通知。它們?yōu)榻M件構(gòu)造器的數(shù)組而提供。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Project: A Pixel Art Editor 譯者:飛龍 協(xié)議:CC BY-NC-SA 4...

    Meils 評論0 收藏0
  • JavaScript 編程精解 中文三版 十二、項(xiàng)目:編程語言

    摘要:來源編程精解中文第三版翻譯項(xiàng)目原文譯者飛龍協(xié)議自豪地采用谷歌翻譯部分參考了編程精解第版確定編程語言中的表達(dá)式含義的求值器只是另一個(gè)程序。若文本不是一個(gè)合法程序,解析器應(yīng)該指出錯誤。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Project: A Programming Language 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地采用...

    Near_Li 評論0 收藏0
  • JavaScript 編程精解 中文三版 五、高階函數(shù)

    摘要:高階函數(shù)如果一個(gè)函數(shù)操作其他函數(shù),即將其他函數(shù)作為參數(shù)或?qū)⒑瘮?shù)作為返回值,那么我們可以將其稱為高階函數(shù)。我們可以使用高階函數(shù)對一系列操作和值進(jìn)行抽象。高階函數(shù)有多種表現(xiàn)形式。腳本數(shù)據(jù)集數(shù)據(jù)處理是高階函數(shù)表現(xiàn)突出的一個(gè)領(lǐng)域。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Higher-Order Functions 譯者:飛龍 協(xié)議:CC BY-NC-...

    blastz 評論0 收藏0
  • JavaScript 編程精解 中文三版 七、項(xiàng)目:機(jī)器人

    摘要:來源編程精解中文第三版翻譯項(xiàng)目原文譯者飛龍協(xié)議自豪地采用谷歌翻譯置疑計(jì)算機(jī)能不能思考就相當(dāng)于置疑潛艇能不能游泳。這張圖將成為我們的機(jī)器人在其中移動的世界。機(jī)器人在收到包裹時(shí)拾取包裹,并在抵達(dá)目的地時(shí)將其送達(dá)。這個(gè)機(jī)器人已經(jīng)快了很多。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Project: A Robot 譯者:飛龍 協(xié)議:CC BY-NC-S...

    jas0n 評論0 收藏0
  • JavaScript 編程精解 中文三版 零、前言

    摘要:來源編程精解中文第三版翻譯項(xiàng)目原文譯者飛龍協(xié)議自豪地采用谷歌翻譯部分參考了編程精解第版,這是一本關(guān)于指導(dǎo)電腦的書。在可控的范圍內(nèi)編寫程序是編程過程中首要解決的問題。我們可以用中文來描述這些指令將數(shù)字存儲在內(nèi)存地址中的位置。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Introduction 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地...

    sanyang 評論0 收藏0
  • JavaScript 編程精解 中文三版 十三、瀏覽器中的 JavaScript

    摘要:在本例中,使用屬性指定鏈接的目標(biāo),其中表示超文本鏈接。您應(yīng)該認(rèn)為和元數(shù)據(jù)隱式出現(xiàn)在示例中,即使它們沒有實(shí)際顯示在文本中。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:JavaScript and the Browser 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《JavaScript 編程精解(第 2 版)》 ...

    zhiwei 評論0 收藏0

發(fā)表評論

0條評論

kamushin233

|高級講師

TA的文章

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