本文主要記錄平時開發遇到的知識點和小技巧javascript
類型相同: 判斷其值是否相同java
類型不一樣:android
1. 若是數字和字符串比較, 則字符串會被隱式轉換爲數字,在作判斷。 2. 若是有一方是布爾值, 則true 轉換爲 1, false 轉換爲 0 ,再進行判斷。 3. 若是其中有一個值爲對象, 則對象會調取自身的valueOf 或者toString方法進行轉換,再作判斷。 4.undefined 與 null 相等。
類型不一樣: 返回false 類型相同: 1. 若是同爲數字/字符串, 則比較值 2. 若是同爲布爾值, 相同則爲true, 不一樣爲false 3. 若是兩個操做數同爲引用類型,且引用的爲同一個對象(函數,數組),則相同。
因此使用 === 進行邏輯判斷的時候,本身就要很清楚兩邊的數據類型。 好比調用函數獲得的是字符串'1', 與 數字 1 比較的時候,獲得的false, 不要犯相似的低級錯誤。編程
javascript中, this表示當前上下文, 即調用者的引用。segmentfault
var tom = { sex: 'M', age: 20 } var jerry = { sex: 'F', age: 18 } function getAge() { return this.age; } console.log(getAge.call(tom)); // 20 console.log(getAge.call(jerry)); // 18 // 經過call 方法, 改變了getAge函數中this的指向, this不會指向getAge函數自己。 var person = { first: 'john', last: 'tom', getFull: function () { console.log(this.first + ' ' + this.last); } } person.getFull(); // john tom //this 指向person var firstName = 'will'; var lastName = 'smith'; function getFull() { console.log(this.firstName + ' ' + this.lastName); } getFull(); // will smith //調用者是window,因此 this 指向window。 function a() { console.log(this); } a.call(null);
call 調用一個對象的一個方法,以另外一個對象替換當前對象。 數組
格式如 call(thisObj, arg1,arg2...argN);瀏覽器
在函數體外部調用call()方法,若是傳入null,則默認轉成window,若是不傳也是同樣,即函數中的this指向window。
console.log(this) // window;閉包
function a() { console.log(this === window); } console.log(this === window); // true a.call(); // true a.call(null); // true a.call(this); // true a.call(window); // true a(); // true
this 的值並不是取決於如何被定義, 而是取決於
調用方式
。
更多有關函數調用的內容請翻閱javascript語言精粹第四章的函數部分。
更多有關this的內容能夠翻閱《你不知道的javascript上卷》第二章。app
JavaScript會將全部變量和函數聲明移動到它的做用域的最前面,這就是所謂的變量提高(Hoisting)。函數
也就是說,不管你在什麼地方聲明變量和函數,解釋器都會將它們移動到做用域的最前面。所以咱們能夠先使用變量和函數,然後聲明它們.
可是,僅僅是變量聲明被提高了,而變量賦值不會被提高。
若是你不明白這一點,有時則會出錯:
console.log(a); // 輸出undefined a = 2; // 初始化y // 上面的代碼等同於 var a; // 聲明y console.log(a); // 輸出undefined a = 2; // 初始化y
再看一個:
var a; console.log(a); a = 1; function a() { // xxx } 輸出: /* function a() { // xxx } 1 */
javascript永遠是先解析聲明函數,再解析變量。
執行順序以下:
(1) 解析函數a;
(2) 聲明變量var a; 由於a此時並無被賦值,因此它爲 undefined, 仍是指向原來的值,即函數 function a;
(3) console.log(a); // function a
(4) a = 1; // 從新賦值, 輸出1
javascript中是沒有函數重載的,可是javascript的函數沒有限制傳入的參數個數必須與函數接收參數的個數相同,因此咱們能夠利用這一特性來模擬函數重載。
舉個栗子:
function add() { if (arguments.length < 2) { return arguments[0]; } else { var _args = [].slice.call(arguments); return _args.reduce(function (a, b) { return a + b; }) } } add(1); // 1 add(1, 2, 3, 4); // 10
舉個計算日期的栗子:
// .. getFutureDate: function(startDate, afterYear, afterMonth, afterDay) { var futureDate, year, month, day; if (arguments.length === 3) { afterDay = arguments[2]; afterMonth = arguments[1]; afterYear = arguments[0]; startDate = new Date(startDate); } if (arguments.length === 4 && Object.prototype.toString.call(startDate) !== "[object Date]") { startDate = new Date(startDate); getFutureDate: function (startDate, afterYear, afterMonth, afterDay) { var futureDate, year, month, day; if (arguments.length === 3) { afterDay = arguments[2]; afterMonth = arguments[1]; afterYear = arguments[0]; startDate = new Date(startDate); } if (arguments.length === 4 && Object.prototype.toString.call(startDate) !== "[object Date]") { startDate = new Date(startDate); } //計算年 futureDate = startDate.setFullYear(startDate.getFullYear() + parseInt(afterYear)); futureDate = new Date(futureDate); // 計算月 futureDate = futureDate.setMonth(futureDate.getMonth() + parseInt(afterMonth)); futureDate = new Date(futureDate); // 計算日 futureDate = futureDate.setDate(futureDate.getDate() + parseInt(afterDay)); futureDate = (new Date(futureDate)); year = futureDate.getFullYear(); month = futureDate.getMonth() + 1; month = month < 10 ? '0' + month : month; day = futureDate.getDate(); day = day < 10 ? '0' + day : day; futureDate = [year, month, day].join('-'); return futureDate }, initDateTime: function () { // ... var endTime = _that.getFutureDate(new Date(today.replace(/-/g, "/")).getTime(), 0, maxInsuranceMonth, maxInsuranceDay); // ... } // ...
var ary = [1, 2, 3, 4, 5]; var res = ary.map(function (item, index, input) { return item * 10; }); console.log(res); // [10, 20, 30, 40, 50] console.log(ary); // [1, 2, 3, 4, 5]
map 函數的實現:
Array.prototype.map = function (func /*, obj */) { var len = this.length; //check the argument if (typeof func != "function") { throw new Error("argument should be a function!"); } var res = []; var obj = arguments[1]; for (var i = 0; i < len; i++) { //func.call(), apply the func to this[i] res[i] = func.call(obj, this[i], i, this); } return res; }
map:和forEach很是類似,都是用來遍歷數組中的每一項值的,用來遍歷數組中的每一項;
區別:map的回調函數中支持return返回值;return的是啥,至關於把數組中的這一項變爲啥(並不影響原來的數組,只是至關於把原數組克隆一份,把克隆的這一份的數組中的對應項改變了);
前面已經說過,this會指向調用者,因此this是指向須要用到map函數的數組的。
須要注意的是,map函數是接收2個參數的,第二個參數是第一個參數的函數this指向。
柯里化就是預先將函數的某些參數傳入,獲得一個簡單的函數,可是預先傳入的參數被保存在閉包中,所以會有一些奇特的特性。
var adder = function(num) { return function(y) { return num + y; } } console.log(adder(1)(100)); // 101 console.log(adder(2)(100)); // 102
更多內容請翻閱上一篇介紹《邂逅函數柯里化》
遞歸在編程中會常用,在某些時候,遞歸能夠給咱們減小不少代碼冗餘。
好比咱們的求階乘函數:
function factorial(n) { if (n == 1) { return 1; } else { return n * factorial(n - 1); } }
函數不停的調用自身,來達到不停的向下求值相乘,從而實現階乘求值。代碼邏輯也一目瞭然。
var UA = (function (userAgent) { var ISOldIOS = /OS (\d)_.* like Mac OS X/g.exec(userAgent), isOldAndroid = /Android (\d.*?);/g.exec(userAgent) || /Android\/(\d.*?) /g.exec(userAgent); // 判斷設備是不是IOS7如下 // 判斷設備是不是android4.5如下 // 判斷是否iOS // 判斷是否android // 判斷是否QQ瀏覽器 return { oldIOS : ISOldIOS ? +ISOldIOS.pop() < 8 : false, oldAndroid: isOldAndroid ? +isOldAndroid.pop().substr(0, 3) < 4.5 : false, iOS : /\(i[^;]+;( U;)? CPU.+Mac OS X/.test(userAgent), android : /Android/g.test(userAgent), mQQBrowser: /MQQBrowser/g.test(userAgent) } })(navigator.userAgent);