1. 程式人生 > >JavaScript中的小技巧和注意點(二)

JavaScript中的小技巧和注意點(二)

tip:自己收集的一些前端注意事項

1.函式優先

函式宣告和變數宣告都會被提升,但是一個值得注意的細節是函式會首先被提升,然後才是變數

foo();//1
var foo;
function foo(){
    console.log(1);
}
foo=function(){
    console.log(2);
};

會輸出1而不是2,這個程式碼片會被引擎理解如下形式:

function foo(){
    console.log(1);
}
foo();//1
foo=function(){
    console.log(2);
};

注意,var foo儘管出現在function foo()…的宣告之前,但它是重複的宣告(因此被忽略了),因為函式宣告會被提升到普通變數之前。

2.迴圈和閉包

當函式可以記住並訪問所在的詞法作用域時,就產生了閉包,即使函式是在當前詞法作用域之外執行。

for(var i=1;i<=5;i++){
    setTimeout(function timer() {
        console.log(i);
    },i*1000);
}

正常情況下,我們對這段程式碼行為的預期是分別輸出數字1-5,每秒一個,每次一個,但實際上,這段程式碼在執行時會以每秒依次的頻率輸出五次6。
(1)通過立即執行函式IIFE進行修正。

for(var i=1;i<=5;i++){
    (function (j) {
setTimeout(function timer() { console.log(j); },j*1000); })(i); }

(2)更簡單的方法,使用let生成塊級作用域。

for(let i=1;i<=5;i++){
    setTimeout(function timer() {
        console.log(i);
    },i*1000);
}

3.被忽略的this

如果你把null或者undefined作為this的繫結物件傳入call,apply或者bind,這些值在呼叫時會被忽略,實際應用的是預設繫結規則

function foo(){
    console.log(this.a);
}
var a=2;
foo.call(null);//2

一種非常常見的做法是使用apply()來展開一個數組,並當作引數傳入一個函式;類似的,bind()可以對引數進行柯里化。
然而,總是使用null來忽略this繫結可能產生一些副作用,導致一些難以分析和追蹤的bug。更安全的做法是傳入一個空物件。在JavaScript中建立一個空物件最簡單的方法是Object.create(null)。
Object.create(null)和 { }很像,但是並不會建立Object.prototype這個委託,所以它比 { } “更空”

4.隱式丟失

一個最常見的this繫結問題就是被隱式繫結的函式會丟失繫結物件,從而把this繫結到全域性物件或者undefined上,取決去是否是嚴格模式。
引數傳遞就是一種隱式賦值,因此傳入函式時會被隱式賦值。

function foo(){
    console.log(this.a)
}
var obj={
    a:2,
    foo:foo
};
var a='oops,global';
setTimeout(obj.foo,1000);//oops,global

JavaScript環境中內建setTimeout()函式實現和下面的虛擬碼類似,可以看出obj.foo被賦值給了fn,所以foo中的this被繫結到了全域性物件上。

function setTimeout(fn,delay){
    //等待delay毫秒
    fn();
}

5.物件屬性存在性

var obj={
    a:undefined
}

物件屬性訪問返回值可能是undefined,但是這個值有可能是屬性中儲存的undefined,也可能是因為屬性不存在而返回undefined

"a" in obj;//true
obj.hasOwnProperty("a");//true

但是有的物件可能沒有連線到Object.prototype(比如通過Object.create(null)來建立的),這種情況下形如obj.hasOwnProperty()就會失敗,這時可以使用一種更加強硬的方法來進行判斷。

Object.prototype.hasOwnProperty.call(obj,"a");

6.計時器

由於歷史原因,setTimeout()和setInterval()的第一個引數可以作為字串傳入。如果這麼做,那麼這個字串就會在指定的間隔之後進行求值(相當於執行eval())

setTimeout('console.log(123)',1000)

7.值和型別

JavaScript中的變數是沒有型別的,只有值才有,變數可以隨時持有任何型別的值,即一個變數可以現在被賦值為字串型別值,隨後又被賦值為數字型別值。
在對變數執行typeof操作時,得到的結果並不是該變數的型別,而是該變數持有的值的型別,因為JavaScript中的變數沒有型別。
已在作用域中宣告但還沒賦值的變數是undefined。相反,還沒有在作用域中宣告過的變數是undeclared,讓人抓狂的是typeof處理undeclared變數的方式同樣返回“undefined”

var a;
typeof a;//undefined
typeof b;//undefined

8.陣列的鍵值

陣列通過數字進行索引,但有趣的是它們也是物件,所以也可以包含字串鍵值和屬性(但是,這些並不計算在陣列長度內!!!)

var a=[]
a[0]=1
a['foo']=2
a.length    //1

這裡有個問題需要特別注意,如果字串鍵值能夠被強制型別轉換為十進位制數字的話,它就會被當作數字索引來處理。

var a=[]
a['3']=3
a.length    //4

9.頁面擁有ID的元素會建立全域性變數

在一張HTML頁面中,所有設定了ID屬性的元素會在JavaScript的執行環境中建立對應的全域性變數,這意味著document.getElementById像人的闌尾一樣顯得多餘了。但實際專案中最好老老實實該怎麼寫就怎麼寫,畢竟常規程式碼出亂子的機會要小得多。

<div id="sample"></div>
<script type="text/javascript">
        console.log(sample);
</script>

10.if語句的變形

當你需要寫一個if語句的時候,不妨嘗試另一種更簡便的方法,用JavaScript中的邏輯操作符來代替。

var day=(new Date).getDay()===0;
//傳統if語句
if (day) {
    alert('Today is Sunday!');
};
//運用邏輯與代替if
day&&alert('Today is Sunday!');

11.數字的語法

對於 . 運算需要給予特別注意,因為它是一個有效的數字字元,會被優先識別為數字常量的一部分,然後才是物件屬性訪問運算子。

// 無效語法
42.toFixed(3)

// 有效語法
(42).toFixed(3) //"42.000"
0.42.toFixed(3) //"0.420"
42..toFixed(3)  //"42.000"
42 .toFixed(3)

42..toFixed(3)沒有問題,因為第一個.被視為number的一部分,第二個.是屬性訪問運算子

12.獲取當前時間

ES5引入了靜態函式Date.now()來獲取當前時間,Date.now()同樣返回毫秒數

if(!Date.now){
    Date.now = function() {
        return (new Date()).getTime()
    }
}

相關推薦

JavaScript中的小技巧注意

tip:自己收集的一些前端注意事項 1.函式優先 函式宣告和變數宣告都會被提升,但是一個值得注意的細節是函式會首先被提升,然後才是變數 foo();//1 var foo; function foo(){ console.log(1);

vue中mixins的使用方法注意

mixins基礎概況 vue中的解釋是這樣的,如果覺得語言枯燥的可以自行跳過嘿~ 混入 (mixins): 是一種分發 Vue 元件中可複用功能的非常靈活的方式。混入物件可以包含任意元件選項。當元件使用混入物件時,所有混入物件的選項將被混入該元件本身的選項。 怎麼用? 舉個栗子: 定義一個混入

python基礎注意

 每個模組都有一個__name__屬性,當其值是'__main__'時,表明該模組自身在執行,否則是被引入。 說明:__name__ 與 __main__ 底下是雙下劃線, _ _ 是這樣去掉中間的那個空格。 內建的函式 dir()

JavaScript的原型原型鏈

constructor建構函式 我們昨天說建立物件的三種方式,第二種是通過new建立物件 let obj = new Object()//建立一個空物件等同於 var obj = {} console.log(obj.constructor === Object)//true

Swift開發中遇到的注意

這段時間開發專案的同時在看第三方庫Kingfisher的實現,感覺有一些東西也需要記錄和總結一下。 6. public private(set),public fileprivate(set) 這和weak一樣是變數的一種修飾,意思是該變數可以public訪

Android中Service的使用詳解注意LocalService

開始,先稍稍講一點android中Service的概念和用途吧~ Service分為本地服務(LocalService)和遠端服務(RemoteService): 1、本地服務依附在主程序上而不是獨立的程序,這樣在一定程度上節約了資源,另外Local服務因為是在同一程序因此

JavaScript的進階之路函數簡介,變量、作用域內存問題

ret 優化 person get 簡介 web瀏覽器 都是 add 是把 <h3>ECMAScript中函數不存在函數簽名的概念,沒有重載</h3><h3>無需指定返回值,可以在任何時候返回任何值。未指定返回值的函數,返回的是一個特殊

JavaScript 系列--JavaScript一些奇淫技巧的實現方法數字格式化 1234567890轉1,234,567,890;argruments 物件(類陣列)轉換成陣列

一、前言 之前寫了一篇文章:JavaScript 系列--JavaScript一些奇淫技巧的實現方法(一)簡短的sleep函式,獲取時間戳 https://www.mwcxs.top/page/746.html 介紹了sleep函式和獲取時間戳的方法。接下來我們來介紹數字格式化1234567890&nb

學好Spark/Kafka必須要掌握的Scala技術類、單例/伴生物件、繼承trait,模式匹配、樣例類case class

3. 類、物件、繼承和trait 3.1 類 3.1.1 類的定義 Scala中,可以在類中定義類、以在函式中定義函式、可以在類中定義object;可以在函式中定義類,類成員的預設訪問級別是:public //在Scala中,類不用宣告為public //Scala原始檔中可以包含多個類,所有這些類都具有公

Javascript面向對象編程:構造函數的繼承

沒有 cal type 這一 今天 nts 實現繼承 刪除 函數綁定 今天要介紹的是,對象之間的"繼承"的五種方法。 比如,現在有一個"動物"對象的構造函數。   function Animal(){     this.species = "動物";   } 還有一個

命令符號總結

命令2017-05-13隨記—————————————————————————————— 20.uname 顯示系統內核信息 -r 顯示內核版本 -m 32位,64位本文出自 “一個Linux小白-學習運維” 博客,謝絕轉載!命令和符號總結(二)

linux高級技巧:rsync同步

十分 src 一次 art 文件夾 ont 關於 技巧 高級 1.配置兩個節點同步 上個帖子已經展示了同步一個主機的方法。這次我們再加入一個要同步的主機。方法上並無二質。 1.首先顯示我們的控制臺:

SpringMVC中文件的上傳上傳到服務器下載問題--------下載

cat exc stream log trac close pri page fin 一、建立一個簡單的jsp頁面。 我們在建好的jsp的頁面中加入一個超鏈接:<a href="${pageContext.request.contextPath}/down

Java2實用教程第5版重要點及遺漏

變量 每一個 實現接口 變量名 等於 優勢 2層 4.3 管理 3.2 語句概述 一個分好也是一條語句,稱作空語句。 3.3.1 if語句 If(表達式) If後面的一堆小括號()內的表達式的值必須是boolean類型 3.3.2 if-else語句 If-else

Java數據結構算法——數組

image 創建 函數 編程 局限性 總結 遍歷數組 ron 添加   上篇博客我們簡單介紹了數據結構和算法的概念,對此模糊很正常,後面會慢慢通過具體的實例來介紹。本篇博客我們介紹數據結構的鼻祖——數組,可以說數組幾乎能表示一切的數據結構,在每一門編

Spring Cloud--鴻鵠Cloud分布式微服務雲系統—技術

oop osql oot api 可能 stream dock dfs base 鴻鵠Cloud是基於springcloud的,spring cloud本身提供的組件就很多,但我們需要按照企業的業務模式來定制企業所需要的通用架構,那我們現在需要考慮使用哪些技術呢? 下面我針

Python 爬取網頁中JavaScript動態添加的內容

python tab sta exe div int rom ava script 使用 selenium + phantomjs 實現 1、準備環境 selenium(一個用於web應用程測試的工具)安裝:pip install seleniumphantomjs(是

Spring整合Struts2Hibernate+Maven之SSH的配置檔案

上次講到的是maven專案的建立以及pom.xml的配置。 這裡推薦一個網站:maven整合jar包,這裡可以查詢並生成配置檔案中jar包匯入格式的文字,複製貼上到pom.xml中即可由idea自動下載並匯入專案。 resources資料夾 建立ssh的配置檔案至上章圖片中的res

資料結構演算法緒論

1、演算法概念 不同的演算法可以提高計算相同算術題的效率,那麼演算法的研究就變得有意義了。 2、演算法的特性 輸入 輸出 有窮性(執行有限的步驟) 確定性(每一個步驟僅有一個含義) 可行性 3、演算法設計要求 沒有無法錯誤、有合法輸入和輸出 4、演算法效率 度量方法: 事前分析估算方法

Java抽象類接口

system args 程序 包含 多重 代碼 apt r.java 可擴展 ***************************接口********************************* 一.why 需求一直不變的時候可以不使用接口, 需求經常發生改變推薦使