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