javascript中那些奇怪的特性

2021-01-09 程式設計師百科

JavaScript 通常被認為是最容易掌握的語言,也是最難掌握的語言。 我完全贊同。 這是因為 JavaScript 是一種非常古老且非常靈活的語言。 它充滿了神秘的語法和過時的功能。 我已經使用 JavaScript 多年了,迄今為止,我仍時不時地發現一些我從未知道的隱藏語法或技巧。

比如下圖,讓很多前端程式設計師感到很無奈。

奇葩的javascript

我曾嘗試過列出一些鮮為人知的 JavaScript 特性, 儘管這些功能在嚴格模式下是無法使用的,但它們仍然是完美的JavaScript 代碼。請牢記,我並不建議使用全部的特性,這會讓你的同事變得暴躁儘管這些特性看起來很酷。

注意:我這裡談到的並不包括,提升,閉包,代理,原形繼承,異步,生成器等。雖然以上這些特性不易理解,但是卻非常實用。

Void操作符

JavaScript 有一個一元的void操作符。你可能已經看到它被用作void(0)或void 0。它在生活中有一個目的——計算一個表達式並返回undefined。使用「0」只是一種約定。 你不必使用「0」, 它可以是任何有效的表達式,如void <expression>,它仍然返回undefined。

void 操作符

為什麼要創建一個特殊的關鍵字來返回undefined而不是直接返回undefined?聽起來有點多餘,不是嗎?有趣的事實好吧,事實證明,在ES5之前,你實際上可以在大多數瀏覽器中為原始未定義的類用undeunfined =「abc」分配新值。因此,定義未定義!在那些日子裡,使用void是一種確保的方法,你總是返回原來的undefined。

構造函數括號是可選的

是的,我們在調用構造函數時在類名後添加括號 - 完全可選!(前提是您不需要將任何參數傳遞給構造函數)

下面的代碼樣式都被認為是有效的JS語法,並且會給你完全相同的結果!

構造函數括號是可選的

可以跳過立即調用的函數表達式括號

對於我來說,立即調用的函數表達式的語法總是有點奇怪.

所有括號都有什麼用?

事實證明,這些額外的括號僅僅是為了告訴JavaScript解析器,即將到來的代碼是一個函數表達式,而不是一個函數。可以想像,知道了這一點,有很多方法可以跳過這些額外的括號,仍然可以生成一個有效的立即調用的函數表達式。

void操作符告訴解析器代碼是函數表達式,因此,我們可以跳過函數定義的括號。

你猜怎麼著?我們可以使用任何一元運算符(void, +, !, -, etc.),這仍然有效!

這太酷了!

但是,如果你是一個敏銳的觀察者,你可能會想,

一元運算符不會影響IIFE返回的結果嗎?

那麼,它會影響結果。 但好消息是,如果您關心結果並說您將其存儲在某個變量中,那麼您首先不需要額外的括號。

確實如此!

IIFE 的返回

我們添加這些括號只是為了更好的可讀性。

如果想深入了解 IIFE,請查看Chandra Gundamaraju 的這篇很酷的文章。

With語句

你知道JavaScript有with語句塊嗎?事實上with是JS中的一個關鍵詞。編寫with語句塊的語法如下

with (object) statement // for multiple statements add a blockwith (object) { statement statement ...}

with會把傳入對象的所有屬性添加進來, 並在其作用域內計算語句的值.

with 塊例子

Fun FactWith聽起來很酷, 不是嗎? 甚至好過 object destructuring 語句.其實不然.with 語句一般不鼓勵使用, 因為它已被廢棄. 在嚴格模式下,它是被完全禁止使用的. 事實證明, with 帶來了性能和安全問題. 真倒黴!

函數構造器

function語句不是唯一的方式來定義新的函數; 你也可以使用Function() 構造器和 new 操作符來動態地定義函數.

使用Function構造器的動態函數

最後一個構造器參數是函數體轉換字符串以後的代碼,它之前的參數是函數的參數.

Fun Fact在JavaScript中,Function構造器是所有構造器的父類. 甚至Object的構造器也是 Function 構造器. 並且Function自己的構造器是Function本身. 不過, 在JavaScript中,任何對象調用object.constructor.constructor...多次後,最終會返回一個Function構造器 .

函數屬性

我們都知道函數在 JavaScript 中是一等公民對象。因此,我們可以自由地給函數對象添加自定義屬性。這在 JS 中絕對沒有問題,但是很少有人會這樣做。

那麼,什麼時候我們應該這樣做呢?

這裡會講到一些不錯的使用場景,比如:

配置函數

假如我們有一個叫 greet的函數,我們希望它能根據不同的地域設置列印出不同的問候語,而位置是可配置的。我們當然可以配置一個全局變量來做這個事情,不過也可以像下面的代碼這樣,使用函數屬性來實現這一功能:

有 locale 屬性的 greet 函數

帶有靜態變量的函數

還有一種類似的用法。如果你想實現一個數字生成器,它會按順序產生一系列的數。一般情況下,可以使用帶有靜態變量的類或IIFE,使用這個靜態變量來保存產生的最後一個數。使用這種方法,我們可以限制對計數器的訪問,並且可以避免全局汙染。

但是如果我們想靈活地讀取甚至修改計數器,同時又能保持沒有全局汙染,應該怎麼辦呢?

我們仍然可以創建一個類,使用計數器變量並通過特殊的方法來讀取它;我們也可以用簡單一點的辦法,使用函數上的屬性。

具有 counter 屬性的 generateNumber 函數

哎呀!這個清單很長,我們已經快進行到一半了。如果你想休息一下,現在就是個不錯的時機。如果你仍然精神振奮,我向你致敬,鬥士。繼續!

arguments 的屬性

我相信大多數人都知道函數中的

arguments

對象。這是一個數組形式的對象,所有函數中都可用。這個對象包含了函數調用時傳入的所有參數列表。但除此之外,它還有一些很有意思的屬性,

arguments.callee: 引用當前調用的函數(即自身)arguments.callee.caller: 引用調用當前函數的那個函數(即調用者)

callee & caller

注意:雖然 ES5 在嚴格(strict)模式下禁止使用callee和caller,但他們仍然普遍存在於很多已經編譯的庫中。所以,學習他們並非毫無意義。

帶標籤的模板字符串

如果你不是生活在原始社會,那就一定聽說過模板字符串。模板字符串是 ES6 中新增的眾多優秀特性之一。不過,話說回來,你知道帶標籤的模板字符串嗎?

模板字符串

帶標籤的模板字符串能讓你更好地控制從模板解析成字符串的過程,它比普通的模板字符串只是多了一個自定義的標籤。這個標籤代表著一個解析函數,它會得到從模板字符串解析出來的字符串和值列表,通過邏輯處理返回最終的生成的字符串。

下面的示例中,我們定義一個標籤 —— highlight,它會將模板字符串解析出來的值處理成 <mark> 元素,使之高亮。

帶標籤的模板字符串 - highlight

已經存在不少庫在使用這個有趣的特性,比如下面這些,React 的 styled-components用於翻譯和國際化的 es2015-i18n-tag用於為輸出上色的chalk

Getters & Setters

在大多數情況下, javascript 對象很簡單。假設我們有一個

user

對象, 我們試圖訪問其上的age屬性,可使用

user.age

我,如果其已被定義,我們將得到age屬性的值, 否則,我們將得到undefined。簡單吧。

但是, 不一定非要這麼簡單。javascript對象有Getters和Setters的概念。我們可以編寫自定義Getter函數來返回所需的任意內容, 而不是直接返回對象上的值。設置值也可同樣處理。

這使我們在獲取或設置欄位時能夠擁有強大的概念, 如虛擬欄位、欄位校驗、副作用

ES5 Getters & Setters

Getters & Setters並不是ES5新加的;他們一直都在那裡。ES5 只是向現有功能添加了便捷的語法。要了解更多關於Getters & Setters的信息, 請參閱這篇文章

Colors,一個流行的node.js庫,是使用Getter的很棒的例子。該庫e擴展自String類,並在其上添加了大量Getter方法。這允許我們將任何字符串轉換為其彩色化版本, 以便於日誌記錄, 僅需簡單訪問它對應的屬性即可。

逗號運算符

javascript 支持逗號運算符。它允許我們在一行中編寫用逗號分隔的多個表達式, 並返回最後一個表達式的結果

// 語法let result = expression1, expression2,... expressionN

在這裡, 將對所有表達式進行計算, 並為結果變量賦值為expressionN的返回值。

你可能已經在 for 循環中使用過逗號運算符了

for (var a = 0, b = 10; a <= 10; a++, b--)

有時在一行中編寫多個語句,它是很有所幫助

functiongetNextValue() { return counter++, console.log(counter), counter}

或編寫簡短的lamda函數

const getSquare = x => (console.log (x), x * x)

+ 加號運算符

你曾經需要將字符串快速轉換為數字嘛?

只要在字符串前面添加+運算符前綴即可。加號運算符也適用於負號、八進位、十六進位、指數值。另外,它甚至可以將日期或Moment.js對象轉換為時間戳!

加號運算符

!! 砰砰運算符

好吧, 從技術上講, 這不是一個獨立的javascript 運算符。這只是使用了兩次的javascript否定運算符。

但砰砰聽起來太酷了!砰砰或雙砰是將任意表達式轉換為布爾值的巧妙技巧。

如果表達式是真值, 它返回true;。否則它返回false。

砰砰運算符

~ 波浪運算符

讓我們面對現實吧--沒有人關心位運算符。我們什麼時候才能使用它呢!

好吧, 有一個波浪或位否定運算符的日常用例。

原來, 當與數字一起使用時, 波浪運算符有效地執行了

~N => -(N+1)

。只有當

N == -1

時, 此表達式的計算結果為 "0"

我們可以通過將~放在

indexOf(...)

函數前面來執行布爾檢查, 是否某個項存在於一個字符串或數組之中。

使用波浪運算符的indexOf函數

注: ES6 & ES7分別在String及Array中添見了新的.includes()方法。當然, 它是一種比波浪運算符更簡潔的方式來檢查某項是否存在於數組或字符串中。

帶標籤的語句

javascript中有

label

語句的概念。它允許我們在 javascript 中命名循環和塊。然後, 我們可以使用這些標籤在後續使用

break

continue

時引用此代碼。

在嵌套循環中, 帶標記的語句特別方便。但我們也可以使用它們簡單地將代碼組織到塊中或創建一個可中斷的塊

帶標籤的語句

註:不同於其他語言,JavaScript並不支持goto建構。因此,我們只能在標籤中使用break和continue。

相關焦點

  • Javascript 生成器
    在 javascript 中,如果想要使用生成器,則需要: 定義特殊的生成器函數 調用該函數創建一個生成器對象 在循環中使用該生成器對象,或直接調用其 方法 我們以下面這個簡單的程序做為起點,並執行以下每個步驟:
  • 如何在javascript中創建一個對象?
    javascript是一門基於對象而不是面向對象的語言,由於它的這個缺陷,在javascript中實現面向對象時十分彆扭,就比如創建對象,由於在ES6之前沒有class關鍵字,想要創建對象必須依賴以下幾種間接方式。
  • 這一次,徹底弄懂 JavaScript 執行機制
    我們真的要徹底弄明白javascript的執行機制了。1.關於javascriptjavascript是一門單線程語言,在最新的HTML5中提出了Web-Worker,但javascript是單線程這一核心仍未改變。
  • 使用HTML5畫布實現的超棒javascript動畫儀錶板:gauge.js
    使用HTML5畫布實現的超棒javascript動畫儀錶板:gauge.js 在線演示今天我們分享來自guage.js的超棒動畫儀錶板實現,這個類庫使用html5畫布來生成動態的自定義儀錶板
  • javascript這些特點你知道其中幾個?建議前端小白好好看看!
    它是web開發中常用的腳本語言,特別是前端。 JavaScript主要功能是增強網頁互動性能,從而增加網站的用戶粘性。這是開發的初衷,但是後來就偏了大部分用到了web廣告上(各種彈窗廣告)。javascript有哪些特點?
  • JavaScript中typeof和instanceof深入詳解
    一般的初學者,在剛剛學習了基本的javascript語法後,都是通過面向函數來編程的。但是利用原型,我們可以優化一些我們的代碼,使用構造函數: 首先,函數本體中只存放變量: var Calculator = function (decimalDigits, tax) {     this.decimalDigits = decimalDigits;     this.tax = tax; };  其具體的方法通過prototype屬性來設置
  • 3.2.3 JavaScript中for循環語句的使用
    JavaScript中的for循環語句也稱為計次循環語句,一般用於循環次數已知的情況。運作說明:先執行初始化語句,然後判斷循環條件,如果條件表達式的值為false,則結束循環,否則執行循環體中的語句組,完成之後執行迭代語句,最後再次判斷循環條件,來決定結束循環還是繼續循環。
  • JavaScript 2020新特性搶先看!
    在2020年,JavaScript 將會迎來一些新的特性與變化,其中大多數都已經處於提議的最終階段並且已經被安排在2020年發布。有一些特性在最新版的 Chrome 和 Firefox 中已經存在,所以你可以現在就打開瀏覽器一探究竟;如果沒有的話你也可以前往 https://codesandbox.io 在線沙盒 IDE 上去寫寫這些代碼。
  • 3.2.2 JavaScript中do-while循環語句的使用
    JavaScript中的do-while循環語句也稱為後測試循環語句,它先執行一次,然後再測試循環條件是否成立,如果成立則循環,如果不成立則結束循環。所以,do-while循環語句中的循環體語句組至少會執行一次。實例:請應用javaScript中的do-while循環語句編寫計算1+2+…+100的程序,並在頁面中輸出計算的結果。
  • 7個令人興奮的JavaScript新特性
    本文介紹這些新特性處於Stage 3 或者Stage 4 階段,這意味著應該很快在瀏覽器和其他引擎中支持這些特性。一、類的私有變量最新提案之一是在類中添加私有變量的方法。我們將使用 # 符號表示類的私有變量。這樣就不需要使用閉包來隱藏不想暴露給外界的私有變量。class Counter { #x = 0; #increment() { this.
  • JavaScript版本發展及未來新特性
    本文整理了JavaScript的各個版本、對應瀏覽器實現情況以及最新版本JavaScript的新增特性,以供Web開發人員更方便地了解JavaScript,用它來開發更大更複雜的程序。 ECMA委員會正在為下一個版本的JavaScript設計而努力,新版本將名為"Harmony"。大概到明年年底就會推出這個新版本,而這是JavaScript發展歷史上最全面的一次提升。
  • 3.1.5 JavaScript中switch語句的使用
    在JavaScript中使用if-else-if語句可以實現多路選擇功能,但其結構使程序看起來很不清晰,也不容易維護。而switch語句是典型的多路分支(多路選擇)語句,其作用與if-else-if語句基本相同,但switch語句比if-else-if語句更具有可讀性,它可以根據一個表達式的值在給定的多個選擇中選擇一個符合條件的分支來執行。而且switch語句允許在找不到一個匹配條件的情況下能執行默認的一個分支。
  • 迷你世界中那些奇怪的地形,冰原巖漿罕見,都遇過的骨灰級玩家!
    迷你世界可謂是當下最熱門的手機沙盒遊戲之一,眾所周知在遊戲中玩家遇到的地形都是隨機的。就是因為這個特性,導致會在遊戲中出現各種奇怪的地形,有一些甚至違反了常識。下面就來跟大家盤點一下,那些奇怪而且極其罕見的地形,看看你知道多少呢。
  • 第五篇:JavaScript事件處理
    初識JavaScript事件JavaScript語言本身不會產生事件,產生事件的是網頁文檔和網頁文檔中的HTML元素。什麼是事件呢?事件就是網頁文檔或網頁元素對外發出的通知。當HTML元素與用戶發生交互行為時,該元素會觸發相關的交互事件,例如:當用戶用滑鼠單擊網頁中的按鈕時,按鈕會觸發滑鼠單擊事件(onclick)。元素自身也會觸發事件,例如:當圖片元素加載完成後,會觸發加載完成事件(onload)。
  • 前端:用javascript實現一個轉盤小遊戲?
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫本文主要介紹如何使用原生javascript和Css3來實現一個在各大移動應用中經常出現的轉盤遊戲,由於改實現可以有不同方式,如果熟悉canvas的話也可以用canvas實現,本文採用js和css實現主要考慮到複雜度較小性能較好
  • 奇怪的姿勢增加了!那些遊戲中的奇妙造型
    最近,九妹在網上衝浪的時候,發現群友們經常會使用一組奇怪的表情包:由於圖中貓貓的表情過於魔性,這個表情包被沙雕網友迅速改成了各種版本,有這樣的:還有這樣的:你別說,還挺緊扣時事不過說到凹造型,遊戲中的奇怪姿勢倒是真有不少,今天就跟大家聊聊那些遊戲中的奇妙姿勢吧。逼格滿滿的姿勢說起凹造型這事兒,那必然有格鬥遊戲的一席之地,自從格鬥遊戲誕生以來,逼格滿滿的勝利姿勢就層出不窮。
  • 那些生活阿羅拉的普通寶可夢,長相實在奇怪,第一卻是最萌輸出王
    第七世代寶可夢遊戲很有趣別管《太陽/月亮》的評價有多麼兩極分化,但平心而論,這部遊戲還是有很多閃光點的,其中就是那些畫風鮮明,長相稀奇的寶可夢們,雖然它們看起來比較奇怪,畫風也比較特別,但實際上每一隻寶可夢都有著屬於它們自己的長處和特點
  • 20個常用的JavaScript簡寫技巧
    箭頭函數 參考:JavaScript Arrow function https://jscurious.com/javascript-arrow-function/ 8. 模板字符串 我們一般使用 + 運算符來連接字符串變量。
  • 我的世界:貓的叫聲裡出現了奇怪的特性,聽完之後感到詭異!
    為了讓小夥伴們更好地了解遊戲中的內容,希望大家能動動小手關注一下。本期內容最近我的世界20w12a快照版本更新後,又修復了非常多的遊戲特性,其中有一個特性引起了演說家的注意,那就是關於貓的叫聲的問題。Mojang表示,貓的叫聲中有滑鼠的點擊聲,這種特性著實讓人感到詭異。
  • 什麼是JavaScript對象?如何創建並引用?這就告訴你!
    1.2 什麼是對象對象:就類中的一個具體的實物。人類-具體某一個人(張三丰)。動物類-(一個具體的動物-東北虎),家電類-(具體一個比如說電視。)js 中我們包含哪些對象呢?c.使用Object.create方法創建對象var obj1 = {};var obj2 = new Object();var obj3 = Object.create(null);Object是在javascript