摘要:單體內(nèi)置對象對內(nèi)置對象的定義是由實現(xiàn)提供的不依賴于宿主環(huán)境的對象,這些對象在程序執(zhí)行之前就已經(jīng)存在了。還定義了兩個單體內(nèi)置對象和。此外,所有原生引用類型的構(gòu)造函數(shù),像和,也都是對象的屬性。
單體內(nèi)置對象
ECMA-262 對內(nèi)置對象的定義是「由 JavaScript 實現(xiàn)提供的、不依賴于宿主環(huán)境的對象,這些對象在 JavaScript 程序執(zhí)行之前就已經(jīng)存在了」。意思就是說,開發(fā)人員不必顯式地實例化內(nèi)置對象,因為它們已經(jīng)實例化了。前面我們已經(jīng)介紹了大多數(shù)內(nèi)置對象,例如 Object、Array 和 String。ECMA-262 還定義了兩個單體內(nèi)置對象:Global 和 Math。
Global 對象Global 對象可以說是 JavaScript 中最特別的一個對象了,因為不管你從什么角度上看,這個對象都是不存在的。Global 對象在某種意義上是作為一個終極的「兜底兒對象」來定義的。換句話說,不屬于任何其他對象的屬性和方法,最終都是它的屬性和方法。所有在全局作用域中定義的屬性和函數(shù),都是 Global 對象的屬性。本書前面介紹過的那些函數(shù),諸如 isNaN()、isFinite()、parseInt() 以及 parseFloat(),實際上全都是 Global 對象的方法。除此之外,Global 對象還包含其他一些方法。
URI 編碼方法Global 對象的 encodeURI() 和 encodeURIComponent() 方法可以對 URI(Uniform Resource Identifiers,通用資源標(biāo)識符)進(jìn)行編碼,以便發(fā)送給瀏覽器。有效的 URI 中不能包含某些字符,例如空格。而這兩個 URI 編碼方法就可以對 URI 進(jìn)行編碼,它們用特殊的 UTF-8 編碼替換所有無效的字符,從而讓瀏覽器能夠接受和理解。
其中,encodeURI() 主要用于整個 URI,而 encodeURIComponent() 主要用于對 URI 中的某一段進(jìn)行編碼。它們的主要區(qū)別在于,encodeURI() 不會對本身屬于 URI 的特殊字符進(jìn)行編碼,例如冒號、正斜杠、問號和井字號;而 encodeURIComponent() 則會對它發(fā)現(xiàn)的任何非標(biāo)準(zhǔn)字符進(jìn)行編碼。來看下面的例子。
var uri = "http://shijiajie.com/illegal value.htm#start"; console.log(encodeURI(uri)); // "http://shijiajie.com/illegal%20value.htm#start" console.log(encodeURIComponent(uri)); // "http%3A%2F%2Fshijiajie.com%2Fillegal%20value.htm%23start"
使用 encodeURI() 編碼后的結(jié)果是除了空格之外的其他字符都原封不動,只有空格被替換成了 %20。而 encodeURIComponent() 方法則會使用對應(yīng)的編碼替換所有非字母數(shù)字字符。這也正是可以對整個 URI 使用 encodeURI(),而只能對附加在現(xiàn)有 URI 后面的字符串使用 encodeURIComponent() 的原因所在。
一般來說,我們使用 encodeURIComponent() 方法的時候要比使用 encodeURI() 更多,因為在實踐中更常見的是對查詢字符串參數(shù)而不是對基礎(chǔ) URI 進(jìn)行編碼。
與 encodeURI() 和 encodeURIComponent() 方法對應(yīng)的兩個方法分別是 decodeURI() 和 decodeURIComponent()。其中,decodeURI() 只能對使用 encodeURI() 替換的字符進(jìn)行解碼。例如,它可將 %20 替換成一個空格,但不會對 %23 作任何處理,因為 %23 表示井字號 #,而井字號不是使用 encodeURI() 替換的。同樣地,decodeURIComponent() 能夠解碼使用 encodeURIComponent() 編碼的所有字符,即它可以解碼任何特殊字符的編碼。來看下面的例子:
var uri = "http%3A%2F%2Fshijiajie.com%2Fillegal%20value.htm%23start"; console.log(decodeURI(uri)); // http%3A%2F%2Fshijiajie.com%2Fillegal value.htm%23start console.log(decodeURIComponent(uri)); // http://shijiajie.com/illegal value.htm#start
這里,變量 uri 包含著一個由 encodeURIComponent() 編碼的字符串。在第一次調(diào)用 decodeURI() 輸出的結(jié)果中,只有 %20 被替換成了空格。而在第二次調(diào)用 decodeURIComponent() 輸出的結(jié)果中,所有特殊字符的編碼都被替換成了原來的字符,得到了一個未經(jīng)轉(zhuǎn)義的字符串(但這個字符串并不是一個有效的 URI)。
eval() 方法eval() 方法就像是一個完整的 JavaScript 解析器,它只接受一個參數(shù),即要執(zhí)行的 JavaScript 字符串??聪旅娴睦樱?/p>
eval("console.log("hi")");
這行代碼的作用等價于下面這行代碼:
console.log("hi");
當(dāng)解析器發(fā)現(xiàn)代碼中調(diào)用 eval() 方法時,它會將傳入的參數(shù)當(dāng)作實際的 JavaScript 語句來解析,然后把執(zhí)行結(jié)果插入到原位置。通過 eval() 執(zhí)行的代碼被認(rèn)為是包含該次調(diào)用的執(zhí)行環(huán)境的一部分,因此被執(zhí)行的代碼具有與該執(zhí)行環(huán)境相同的作用域鏈。這意味著通過 eval() 執(zhí)行的代碼可以引用在包含環(huán)境中定義的變量,舉個例子:
var msg = "hello world"; eval("console.log(msg)"); // "hello world"
可見,變量 msg 是在 eval() 調(diào)用的環(huán)境之外定義的,但其中調(diào)用的 console.log() 仍然能夠顯示 "hello world"。這是因為上面第二行代碼最終被替換成了一行真正的代碼。同樣地,我們也可以在 eval() 調(diào)用中定義一個函數(shù),然后再在該調(diào)用的外部代碼中引用這個函數(shù):
eval("function sayHi() { console.log("hi"); }"); sayHi(); // "hi"
顯然,函數(shù) sayHi() 是在 eval() 內(nèi)部定義的。但由于對 eval() 的調(diào)用最終會被替換成定義函數(shù)的實際代碼,因此可以在下一行調(diào)用 sayHi() 。對于變量也一樣:
eval("var msg = "hello world";"); console.log(msg); // "hello world"
在 eval() 中創(chuàng)建的任何變量或函數(shù)都不會被提升,因為在解析代碼的時候,它們被包含在一個字符串中;它們只在 eval() 執(zhí)行的時候創(chuàng)建。
嚴(yán)格模式下,在外部訪問不到 eval() 中創(chuàng)建的任何變量或函數(shù),因此前面兩個例子都會導(dǎo)致錯誤。同樣,在嚴(yán)格模式下,為 eval 賦值也會導(dǎo)致錯誤:
"use strict"; eval = "hi"; // causes error
能夠解釋代碼字符串的能力非常強大,但也非常危險。因此在使用 eval() 時必須極為謹(jǐn)慎,特別是在用它執(zhí)行用戶輸入數(shù)據(jù)的情況下。否則,可能會有惡意用戶輸入威脅你的站點或應(yīng)用程序安全的代碼(即所謂的代碼注入)。
Global 對象的屬性Global 對象還包含一些屬性,其中一部分屬性已經(jīng)在本書前面介紹過了。例如,特殊的值 undefined、NaN 以及 Infinity 都是 Global 對象的屬性。此外,所有原生引用類型的構(gòu)造函數(shù),像 Object 和 Function,也都是 Global 對象的屬性。下表列出了 Global 對象的所有屬性。
屬性 | 說明 | 屬性 | 說明 |
---|---|---|---|
undefined | 特殊值undefined | Date | 構(gòu)造函數(shù)Date |
NaN | 特殊值NaN | RegExp | 構(gòu)造函數(shù)RegExp |
Infinity | 特殊值Infinity | Error | 構(gòu)造函數(shù)Error |
Object | 構(gòu)造函數(shù)Object | EvalError | 構(gòu)造函數(shù)EvalError |
Array | 構(gòu)造函數(shù)Array | RangeError | 構(gòu)造函數(shù)RangeError |
Function | 構(gòu)造函數(shù)Function | ReferenceError | 構(gòu)造函數(shù)ReferenceError |
Boolean | 構(gòu)造函數(shù)Boolean | SyntaxError | 構(gòu)造函數(shù)SyntaxError |
String | 構(gòu)造函數(shù)String | TypeError | 構(gòu)造函數(shù)TypeError |
Number | 構(gòu)造函數(shù)Number | URIError | 構(gòu)造函數(shù)URIError |
ECMAScript 5 明確禁止給 undefined、NaN 和 Infinity 賦值,這樣做即使在非嚴(yán)格模式下也會導(dǎo)致錯誤。
window 對象JavaScript 雖然沒有指出如何直接訪問 Global 對象,但 Web 瀏覽器都是將這個全局對象作為 window 對象的一部分加以實現(xiàn)的。因此,在全局作用域中聲明的所有變量和函數(shù),就都成為了 window 對象的屬性。來看下面的例子。
var color = "red"; function sayColor(){ console.log(window.color); } window.sayColor(); // "red"
JavaScript 中的 window 對象除了扮演規(guī)定的 Global 對象的角色外,還承擔(dān)了很多別的任務(wù)。
Math 對象JavaScript 還為保存數(shù)學(xué)公式和信息提供了一個公共位置,即 Math 對象。與我們在 JavaScript 直接編寫的計算功能相比,Math 對象提供的計算功能執(zhí)行起來要快得多。Math 對象中還提供了輔助完成這些計算的屬性和方法。
Math 對象的屬性Math 對象包含的屬性大都是數(shù)學(xué)計算中可能會用到的一些特殊值。下表列出了這些屬性。
屬性 | 說明 |
---|---|
Math.E | 自然對數(shù)的底數(shù),即常量e的值 |
Math.LN10 | 10的自然對數(shù) |
Math.LN2 | 2的自然對數(shù) |
Math.LOG2E | 以2為底e的對數(shù) |
Math.LOG10E | 以10為底e的對數(shù) |
Math.PI | π的值 |
Math.SQRT1_2 | 1/2的平方根(即2的平方根的倒數(shù)) |
Math.SQRT2 | 2的平方根 |
Math 對象還包含許多方法,用于輔助完成簡單和復(fù)雜的數(shù)學(xué)計算。其中,min() 和 max() 方法用于確定一組數(shù)值中的最小值和最大值。這兩個方法都可以接收任意多個數(shù)值參數(shù),如下面的例子所示。
var max = Math.max(3, 54, 32, 16); console.log(max); // 54 var min = Math.min(3, 54, 32, 16); console.log(min); // 3
要找到數(shù)組中的最大或最小值,可以像下面這樣使用 apply() 方法。
var values = [1, 2, 3, 4, 5, 6, 7, 8]; var max = Math.max.apply(Math, values); console.log(max); // 8
這個技巧的關(guān)鍵是把 Math 對象作為 apply() 的第一個參數(shù),從而正確地設(shè)置 this 值。然后,可以將任何數(shù)組作為第二個參數(shù)。
舍入方法下面來介紹將小數(shù)值舍入為整數(shù)的幾個方法:Math.ceil()、Math.floor() 和 Math.round()。這三個方法分別遵循下列舍入規(guī)則:
Math.ceil() 執(zhí)行向上舍入,即它總是將數(shù)值向上舍入為最接近的整數(shù);
Math.floor() 執(zhí)行向下舍入,即它總是將數(shù)值向下舍入為最接近的整數(shù);
Math.round() 執(zhí)行標(biāo)準(zhǔn)舍入,即它總是將數(shù)值四舍五入為最接近的整數(shù)。
下面是使用這些方法的示例:
console.log(Math.ceil(25.9)); // 26 console.log(Math.ceil(25.5)); // 26 console.log(Math.ceil(25.1)); // 26 console.log(Math.round(25.9)); // 26 console.log(Math.round(25.5)); // 26 console.log(Math.round(25.1)); // 25 console.log(Math.floor(25.9)); // 25 console.log(Math.floor(25.5)); // 25 console.log(Math.floor(25.1)); // 25random() 方法
Math.random() 方法返回介于0和1之間一個隨機數(shù),包括0而不包括1。對于某些站點來說,這個方法非常實用,因為可以利用它來隨機顯示一些名人名言和新聞事件。套用下面的公式,就可以利用 Math.random() 從某個整數(shù)范圍內(nèi)隨機選擇一個值。
值 = Math.floor(Math.random() * 可能值的總數(shù) + 第一個可能的值)
公式中用到了 Math.floor() 方法,這是因為 Math.random() 總返回一個小數(shù)值。而用這個小數(shù)值乘以一個整數(shù),然后再加上一個整數(shù),最終結(jié)果仍然還是一個小數(shù)。舉例來說,如果你想選擇一個1到10之間的數(shù)值,可以像下面這樣編寫代碼:
var num = Math.floor(Math.random() * 10 + 1);
總共有10個可能的值(1到10),而第一個可能的值是1。而如果想要選擇一個介于2到10之間的值,就應(yīng)該將上面的代碼改成這樣:
var num = Math.floor(Math.random() * 9 + 2);
從2數(shù)到10要數(shù)9個數(shù),因此可能值的總數(shù)就是9,而第一個可能的值就是2。多數(shù)情況下,其實都可以通過一個函數(shù)來計算可能值的總數(shù)和第一個可能的值,例如:
function selectFrom(lowerValue, upperValue) { var choices = upperValue - lowerValue + 1; return Math.floor(Math.random() * choices + lowerValue); } var num = selectFrom(2, 10); console.log(num); // 介于2和10之間(包括2和10)的一個數(shù)值
函數(shù) selectFrom() 接受兩個參數(shù):應(yīng)該返回的最小值和最大值。而用最大值減最小值再加1得到了可能值的總數(shù),然后它又把這些數(shù)值套用到了前面的公式中。這樣,通過調(diào)用 selectFrom(2,10) 就可以得到一個介于2和10之間(包括2和10)的數(shù)值了。利用這個函數(shù),可以方便地從數(shù)組中隨機取出一項,例如:
var colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"]; var color = colors[selectFrom(0, colors.length-1)]; console.log(color); // 可能是數(shù)組中包含的任何一個字符串其他方法
Math 對象中還包含其他一些與完成各種簡單或復(fù)雜計算有關(guān)的方法,但詳細(xì)討論其中每一個方法的細(xì)節(jié)及適用情形超出了本書的范圍。下面我們就給出一個表格,其中列出了這些沒有介紹到的 Math 對象的方法。
方法 | 說明 |
---|---|
Math.abs(num) | 返回num的絕對值 |
Math.asin(x) | 返回x的反正弦值 |
Math.exp(num) | 返回Math.E的num次冪 |
Math.atan(x) | 返回x的反正切值 |
Math.log(num) | 返回num的自然對數(shù) |
Math.atan2(y,x) | 返回y/x的反正切值 |
Math.pow(num,power) | 返回num的power次冪 |
Math.cos(x) | 返回x的余弦值 |
Math.sqrt(num) | 返回num的平方根 |
Math.sin(x) | 返回x的正弦值 |
Math.acos(x) | 返回x的反余弦值 |
Math.tan(x) | 返回x的正切值 |
雖然 ECMA-262 規(guī)定了這些方法,但不同實現(xiàn)可能會對這些方法采用不同的算法。畢竟,計算某個值的正弦、余弦和正切的方式多種多樣。也正因為如此,這些方法在不同的實現(xiàn)中可能會有不同的精度。
關(guān)卡// 如何高效產(chǎn)生m個n范圍內(nèi)的不重復(fù)隨機數(shù)(m<=n) var getRandomNumber = function(n, m){ // 待實現(xiàn)方法體 } console.log(getRandomNumber(20, 3)); // 8,4,19更多
關(guān)注微信公眾號「劼哥舍」回復(fù)「答案」,獲取關(guān)卡詳解。
關(guān)注 https://github.com/stone0090/javascript-lessons,獲取最新動態(tài)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80732.html
摘要:對象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對象模型是針對和文檔的一個。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動態(tài)的,根闖關(guān)記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...
摘要:本課程之所以叫做闖關(guān)記,是因為部分章節(jié)精心設(shè)計了挑戰(zhàn)關(guān)卡,通過提供更多的實戰(zhàn)機會,讓大家可以循序漸進(jìn)地有目的地有挑戰(zhàn)地開展學(xué)習(xí)。課程結(jié)構(gòu)及目錄以下目錄只是初步構(gòu)想,課程結(jié)構(gòu)及內(nèi)容會根據(jù)實際情況隨時進(jìn)行調(diào)整。 為何寫作此課程 stone 主要負(fù)責(zé)基于 Web 的企業(yè)內(nèi)部管理系統(tǒng)的開發(fā),雖然能夠熟練地使用 JavaScript,但隨著對 JavaScript 的理解越來越深,才發(fā)現(xiàn)自己尚...
摘要:屬性名可以是包含空字符串在內(nèi)的任意字符串,但對象中不能存在兩個同名的屬性。客戶端中表示網(wǎng)頁結(jié)構(gòu)的對象均是宿主對象。這里的函數(shù)稱做構(gòu)造函數(shù),構(gòu)造函數(shù)用以初始化一個新創(chuàng)建的對象。通過關(guān)鍵字和構(gòu)造函數(shù)調(diào)用創(chuàng)建的對象的原型就是構(gòu)造函數(shù)的屬性的值。 對象是 JavaScript 的數(shù)據(jù)類型。它將很多值(原始值或者其他對象)聚合在一起,可通過名字訪問這些值,因此我們可以把它看成是從字符串到值的映射...
摘要:把上面的函數(shù)聲明改為等價的函數(shù)表達(dá)式,就會在執(zhí)行期間導(dǎo)致錯誤。換句話說,引用的是函數(shù)據(jù)以執(zhí)行的環(huán)境對象當(dāng)在網(wǎng)頁的全局作用域中調(diào)用函數(shù)時,對象引用的就是。這兩個方法的用途都是在特定的作用域中調(diào)用函數(shù),實際上等于設(shè)置函數(shù)體內(nèi)對象的值。 函數(shù)是一段代碼,它只定義一次,但可以被執(zhí)行或調(diào)用任意次。在 JavaScript 里,函數(shù)即對象,程序可以隨意操控它們。比如,可以把函數(shù)賦值給變量,或者作為...
摘要:瀏覽器只是實現(xiàn)的宿主環(huán)境之一,其他宿主環(huán)境包括和。年月,版發(fā)布,成為國際標(biāo)準(zhǔn)。事件定義了事件和事件處理的接口。對于已經(jīng)正式納入標(biāo)準(zhǔn)的來說,盡管各瀏覽器都實現(xiàn)了某些眾所周知的共同特性,但其他特性還是會因瀏覽器而異。 JavaScript 是面向 Web 的編程語言,絕大多數(shù)現(xiàn)代網(wǎng)站都使用了 JavaScript,并且所有的現(xiàn)代 Web 瀏覽器(電腦,手機,平板)均包含了 JavaScri...
閱讀 1146·2019-08-30 12:44
閱讀 653·2019-08-29 13:03
閱讀 2562·2019-08-28 18:15
閱讀 2431·2019-08-26 10:41
閱讀 3092·2019-08-26 10:28
閱讀 3040·2019-08-23 16:54
閱讀 1992·2019-08-23 15:16
閱讀 817·2019-08-23 14:55