摘要:訪問屬性是通過操作符完成的,但這要求屬性名必須是一個有效的變量名小紅的屬性名不是一個有效的變量,就需要用括起來。閉包應(yīng)用封裝私有變量箭頭函數(shù)箭頭函數(shù)相當(dāng)于匿名函數(shù),并且簡化了函數(shù)定義。
數(shù)據(jù)類型
NAN
NaN === NaN; // false
唯一能判斷NaN的方法是通過isNaN()函數(shù):
isNaN(NaN); // true
浮點數(shù)的相等比較:
1 / 3 === (1 - 2 / 3); // false
這不是JavaScript的設(shè)計缺陷。浮點數(shù)在運算過程中會產(chǎn)生誤差,因為計算機(jī)無法精確表示無限循環(huán)小數(shù)。要比較兩個浮點數(shù)是否相等,只能計算它們之差的絕對值,看是否小于某個閾值:
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true
避免使用new Array(1, 2, 3); // 創(chuàng)建了數(shù)組[1, 2, 3]方式
字符串
需要特別注意的是,字符串是不可變的
如果對字符串的某個索引賦值,不會有任何錯誤,但是,也沒有任何效果:
var s = "Test"; s[0] = "X"; alert(s); // s仍然為"Test"
JavaScript為字符串提供了一些常用方法,注意,調(diào)用這些方法本身不會改變原有字符串的內(nèi)容,而是返回一個新字符串
數(shù)組大多數(shù)其他編程語言不允許直接改變數(shù)組的大小,越界訪問索引會報錯。然而,JavaScript的Array卻不會有任何錯誤。在編寫代碼時,不建議直接修改Array的大小,訪問索引時要確保索引不會越界。
對原數(shù)組進(jìn)行操作的方法和返回新數(shù)組的方法
原數(shù)組:
pop/push,unshift/shift
sort
reverse
splice
新數(shù)組:
slice
concat
join返回的是新的字符串
擴(kuò)展:數(shù)組扁平化的幾種方法
var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]];
使用concat()和apply()
var myNewArray = [].concat.apply([], myArray); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
使用reduce()
var myNewArray = myArray.reduce(function(prev, curr) { return prev.concat(curr); }); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
MSDN reduce 方法
使用 ES6 的展開運算符
var myNewArray4 = [].concat(...myArray); console.log(myNewArray4); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
MDN 展開運算符
最后這個方法返回的是字符串
myArray.join(",") //"1,2,3,4,5,6,7,8,9"
請注意,for ... in對Array的循環(huán)得到的是String而不是Number
對象注意,最后一個鍵值對不需要在末尾加,,如果加了,有的瀏覽器(如低版本的IE)將報錯。
訪問屬性是通過.操作符完成的,但這要求屬性名必須是一個有效的變量名
var xiaohong = { name: "小紅", "middle-school": "No.1 Middle School" };
xiaohong的屬性名middle-school不是一個有效的變量,就需要用""括起來。訪問這個屬性也無法使用.操作符,必須用["xxx"]來訪問:
xiaohong["middle-school"]; // "No.1 Middle School" xiaohong["name"]; // "小紅" xiaohong.name; // "小紅"
訪問不存在的屬性不報錯,而是返回undefined
函數(shù)
小心你的return語句
如果把return語句拆成兩行:
function foo() { return { name: "foo" }; } foo(); // undefined
要小心了,由于JavaScript引擎在行末自動添加分號的機(jī)制,上面的代碼實際上變成了:
function foo() { return; // 自動添加了分號,相當(dāng)于return undefined; { name: "foo" }; // 這行語句已經(jīng)沒法執(zhí)行到了 }
所以正確的多行寫法是:
function foo() { return { // 這里不會自動加分號,因為{表示語句尚未結(jié)束 name: "foo" }; }
變量提升
由于JavaScript的這一怪異的“特性”,我們在函數(shù)內(nèi)部定義變量時,請嚴(yán)格遵守“在函數(shù)內(nèi)部首先申明所有變量”這一規(guī)則。
閉包應(yīng)用:封裝私有變量
function create_counter(initial) { var x = initial || 0; return { inc: function () { x += 1; return x; } } }
箭頭函數(shù)
箭頭函數(shù)相當(dāng)于匿名函數(shù),并且簡化了函數(shù)定義。箭頭函數(shù)有兩種格式,一種只包含一個表達(dá)式,連{ ... }和return都省略掉了。還有一種可以包含多條語句,這時候就不能省略{ ... }和return
返回對象:
// SyntaxError: x => { foo: x } // ok: x => ({ foo: x })
箭頭函數(shù)完全修復(fù)了this的指向,箭頭函數(shù)內(nèi)部的this是詞法作用域,由上下文確定
擴(kuò)展:裝飾器
現(xiàn)在假定我們想統(tǒng)計一下代碼一共調(diào)用了多少次parseInt(),可以把所有的調(diào)用都找出來,然后手動加上count += 1,不過這樣做太傻了。最佳方案是用我們自己的函數(shù)替換掉默認(rèn)的parseInt():
var count = 0; var oldParseInt = parseInt; // 保存原函數(shù) window.parseInt = function () { count += 1; return oldParseInt.apply(null, arguments); // 調(diào)用原函數(shù) }; // 測試: parseInt("10"); parseInt("20"); parseInt("30"); count; // 3對象
需要遵守的規(guī)則
不要使用new Number()、new Boolean()、new String()創(chuàng)建包裝對象;
用parseInt()或parseFloat()來轉(zhuǎn)換任意類型到number;
用String()來轉(zhuǎn)換任意類型到string,或者直接調(diào)用某個對象的toString()方法;
通常不必把任意類型轉(zhuǎn)換為boolean再判斷,因為可以直接寫if (myVar) {...};
typeof操作符可以判斷出number、boolean、string、function和undefined;
判斷Array要使用Array.isArray(arr);
判斷null請使用myVar === null;
判斷某個全局變量是否存在用typeof window.myVar === "undefined";
函數(shù)內(nèi)部判斷某個變量是否存在用typeof myVar === "undefined"。
獲取時間戳
if (Date.now) { alert(Date.now()); // 老版本IE沒有now()方法 } else { alert(new Date().getTime()); }
JSON.stringify()
格式化
var xiaoming = { name: "小明", age: 14, gender: true, height: 1.65, grade: null, "middle-school": ""W3C" Middle School", skills: ["JavaScript", "Java", "Python", "Lisp"] }; undefined JSON.stringify(xiaoming, null, " "); "{ "name": "小明", "age": 14, "gender": true, "height": 1.65, "grade": null, "middle-school": ""W3C" Middle School", "skills": [ "JavaScript", "Java", "Python", "Lisp" ] }"
篩選數(shù)據(jù)
第二個參數(shù)用于控制如何篩選對象的鍵值,如果我們只想輸出指定的屬性,可以傳入Array:
JSON.stringify(xiaoming, ["name", "height"], " ");
"{ "name": "小明", "height": 1.65 }"
也可以傳入函數(shù)進(jìn)行處理
瀏覽器
獲取UA
function whatBrowser() { document.Browser.Name.value=navigator.appName; document.Browser.Version.value=navigator.appVersion; document.Browser.Code.value=navigator.appCodeName; document.Browser.Agent.value=navigator.userAgent; }
請注意,navigator的信息可以很容易地被用戶修改,所以JavaScript讀取的值不一定是正確的
cookie安全問題
由于JavaScript能讀取到頁面的Cookie,而用戶的登錄信息通常也存在Cookie中,這就造成了巨大的安全 隱患。為了解決這個問題,服務(wù)器在設(shè)置Cookie時可以使用httpOnly,設(shè)定了httpOnly的Cookie將不能被JavaScript讀取。這個行為由瀏覽器實現(xiàn),主流瀏覽器均支持httpOnly選項,IE從IE6 SP1開始支持。
為了確保安全,服務(wù)器端在設(shè)置Cookie時,應(yīng)該始終堅持使用httpOnly。
按字符串順序重新排序DOM節(jié)點
- Scheme
- JavaScript
- Python
- Ruby
- Haskell
var ol = document.getElementById("test-list"), lis = [].slice.call(ol.children); lis.sort((a,b)=> a.innerText.toUpperCase() > b.innerText.toUpperCase()); lis.forEach(x=>{ol.appendChild(x)})
children屬性時刻都在變化
當(dāng)你遍歷一個父節(jié)點的子節(jié)點并進(jìn)行刪除操作時,要注意,children屬性是一個只讀屬性,并且它在子節(jié)點變化時會實時更新。
例如,對于如下HTML結(jié)構(gòu):
First
Second
當(dāng)我們用如下代碼刪除子節(jié)點時:
var parent = document.getElementById("parent"); parent.removeChild(parent.children[0]); parent.removeChild(parent.children[1]); // <-- 瀏覽器報錯
瀏覽器報錯:parent.children[1]不是一個有效的節(jié)點。原因就在于,當(dāng)
First
節(jié)點被刪除后,parent.children的節(jié)點數(shù)量已經(jīng)從2變?yōu)榱?,索引[1]已經(jīng)不存在了。
擴(kuò)展練習(xí)
把與Web開發(fā)技術(shù)不相關(guān)的節(jié)點刪掉
var parent = document.getElementById("test-list"); var children = [].slice.call(parent.children); //Array.prototype.slice.call() children.forEach((element) => { for(var s of ["Swift", "ANSI C", "DirectX"]){ if(element.innerText == s){ parent.removeChild(element); } } });事件
需要特別注意的是,下面這種寫法是無效的:
// 綁定事件: a.click(function () { alert("hello!"); }); // 解除綁定: a.off("click", function () { alert("hello!"); });
這是因為兩個匿名函數(shù)雖然長得一模一樣,但是它們是兩個不同的函數(shù)對象,off("click", function () {...})無法移除已綁定的第一個匿名函數(shù)。
為了實現(xiàn)移除效果,可以使用off("click")一次性移除已綁定的click事件的所有處理函數(shù)。
同理,無參數(shù)調(diào)用off()一次性移除已綁定的所有類型的事件處理函數(shù)。
事件觸發(fā)條件
一個需要注意的問題是,事件的觸發(fā)總是由用戶操作引發(fā)的,但是,如果用JavaScript代碼去改動,將不會觸發(fā)change事件
有些時候,我們希望用代碼觸發(fā)change事件,可以直接調(diào)用無參數(shù)的change()方法來觸發(fā)該事件
var input = $("#test-input"); input.val("change it!"); input.change(); // 觸發(fā)change事件
input.change()相當(dāng)于input.trigger("change"),它是trigger()方法的簡寫。
瀏覽器安全限制
在瀏覽器中,有些JavaScript代碼只有在用戶觸發(fā)下才能執(zhí)行,例如,window.open()函數(shù):
// 無法彈出新窗口,將被瀏覽器屏蔽: $(function () { window.open("/"); });
這些“敏感代碼”只能由用戶操作來觸發(fā):
var button1 = $("#testPopupButton1"); var button2 = $("#testPopupButton2"); function popupTestWindow() { window.open("/"); } button1.click(function () { popupTestWindow(); }); button2.click(function () { // 不立刻執(zhí)行popupTestWindow(),100毫秒后執(zhí)行: setTimeout(popupTestWindow, 100); });
當(dāng)用戶點擊button1時,click事件被觸發(fā),由于popupTestWindow()在click事件處理函數(shù)內(nèi)執(zhí)行,這是瀏覽器允許的,而button2的click事件并未立刻執(zhí)行popupTestWindow(),延遲執(zhí)行的popupTestWindow()將被瀏覽器攔截。
Ajaxopen方法的第三個參數(shù)
千萬不要把第三個參數(shù)指定為false,否則瀏覽器將停止響應(yīng),直到AJAX請求完成。
跨域方案
flash插件,現(xiàn)在用的很少
代理服務(wù)器,需要服務(wù)器端做額外開發(fā)
jsonp,只支持get請求
cors,通過http頭的Access-Control-Allow-Origin驗證
編寫jquery插件原則給$.fn綁定函數(shù),實現(xiàn)插件的代碼邏輯;
插件函數(shù)最后要return this;以支持鏈?zhǔn)秸{(diào)用;
插件函數(shù)要有默認(rèn)值,綁定在$.fn.
用戶在調(diào)用時可傳入設(shè)定值以便覆蓋默認(rèn)值。
擴(kuò)展jQuery對象的功能十分簡單,但是我們要遵循jQuery的原則,編寫的擴(kuò)展方法能支持鏈?zhǔn)秸{(diào)用、具備默認(rèn)值和過濾特定元素,使得擴(kuò)展方法看上去和jQuery本身的方法沒有什么區(qū)別。
此篇跳過了js中的面向?qū)ο?,高階函數(shù),正則,原型等難點,下篇等我好好研究一下繼續(xù)
參考資料 Javascript多維數(shù)組扁平化
廖雪峰老師的js教程
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80603.html
摘要:巔峰人生年老兵思路上的轉(zhuǎn)變,遠(yuǎn)比單純提升技術(shù)更有價值本文節(jié)選自趙成教授在極客時間開設(shè)的趙成的運維體系管理課,是其對自己十年技術(shù)生涯的回顧與總結(jié)。趙成教授來自美麗聯(lián)合集團(tuán),集團(tuán)旗下兩大主力產(chǎn)品是蘑菇街和美麗說,目前負(fù)責(zé)管理集團(tuán)的技術(shù)服務(wù)團(tuán)隊。 showImg(https://segmentfault.com/img/remote/1460000012476504?w=1240&h=826...
摘要:應(yīng)該非常小心,避免出現(xiàn)不使用命令直接調(diào)用構(gòu)造函數(shù)的情況。上面代碼表示,使用屬性,確定實例對象的構(gòu)造函數(shù)是,而不是。當(dāng)然,從繼承鏈來看,只有一個父類,但是由于在的實例上,同時執(zhí)行和的構(gòu)造函數(shù),所以它同時繼承了這兩個類的方法。 基本概念 類和實例是大多數(shù)面向?qū)ο缶幊陶Z言的基本概念 類:類是對象的類型模板 實例:實例是根據(jù)類創(chuàng)建的對象但是,JavaScript語言的對象體系,不是基于類的,...
摘要:原文發(fā)布在數(shù)組應(yīng)該是日常開發(fā)中最常見的數(shù)據(jù)結(jié)構(gòu)了,雖然常見,但是卻不一定能優(yōu)雅地處理好,中數(shù)組的處理方法很多,各個方法的參數(shù)返回值是否修改原數(shù)組等也容易記混。 原文發(fā)布在:http://blog.xiaofeixu.cn/2017... 數(shù)組應(yīng)該是日常開發(fā)中最常見的數(shù)據(jù)結(jié)構(gòu)了,雖然常見,但是卻不一定能優(yōu)雅地處理好,JavaScript中數(shù)組的處理方法很多,各個方法的參數(shù)、返回值、是否修...
摘要:特意對前端學(xué)習(xí)資源做一個匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對前端學(xué)習(xí)資源做一個匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點多,可以很快搞定,沒想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯誤的地方,還請斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會及時更新,平時業(yè)務(wù)工作時也會不定期更...
閱讀 985·2021-11-22 09:34
閱讀 2168·2021-11-11 16:54
閱讀 2206·2021-09-27 14:00
閱讀 950·2019-08-30 15:55
閱讀 1537·2019-08-29 12:46
閱讀 610·2019-08-26 18:42
閱讀 648·2019-08-26 13:31
閱讀 3191·2019-08-26 11:52