JavaScript 平時記錄

1,JS中的thisjavascript

見下面例子,注意函數中的函數 中的this指的是window對象了!!!php

    document.addEventListener('click', function (e) { console.log(this);//this->document,添加在誰上的事件this就是指的誰
        (function () { console.log(this);//this->window
 })(); }); var o = { a : function () { console.log(this);//this->o,this指代對象o
            var b = function () { console.log(this);//this->window
 }() } }; o.a();//o['a']()

2,定時器函數 setTimeout() 函數說明 (JavaScript單線程相關)html

語法:
var timeoutID = scope.setTimeout(function[, delay, param1, param2,....]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);
java


參數說明:
  function:function 是你想要在delay毫秒以後執行的 回調函數
  code:這是一個替代語法,你可使用字符串代替function ,在delay毫秒以後執行字符串 (使用該語法是不推薦的, 緣由和使用 eval()同樣,有安全風險)。
  delay: 可選延遲的毫秒數 (一秒等於1000毫秒),函數的調用會在該延遲以後發生。若是省略該參數,delay取默認值0。實際的延遲時間可能會比 delay 值長,緣由請查看Reasons for delays longer than specified
  param1, ..., paramN 可選附加參數,一旦定時器到期,它們會做爲參數傳遞給function 或 執行字符串(setTimeout參數中的code)
例子:
  這個函數有兩種用法,第一個參數能夠是一個函數名稱,也能夠是字符串形式的代碼。見下面兩個例子:
  setTimeout("location.reload()", 5000)//5秒以後執行代碼, 刷新頁面
  setTimeout(reload, 4000); //4秒以後執行reload函數
若是這麼寫:setTimeout(location.reload(), 5000);效果是這樣的:頁面一直不停刷新,不會等5秒以後才刷新。緣由是:沒有用字符串形式的第一個參數實際上就是當即執行此代碼,即刷新頁面,刷新頁面後,又從新執行setTimeout()這個函數,而這個函數又一次當即執行location.reload(),如此循環....jquery

深度解析JavaScript中的settimeout()和setInterval()函數: git

https://blog.csdn.net/chiuwingyan/article/details/80322289程序員

http://www.javashuo.com/article/p-udfbgzos-h.htmlgithub

關於JavaScript單線程的一些事正則表達式

小結一下:setTimeout()比setInterval()穩定,通常不使用setInterval()而是使用鏈式調用setTimeout()模擬setInterval()。緣由是JavaScript引擎是單線程的,主要分爲主線程和事件隊列。同步操做是在主線程上執行的,異步操做通常是首先放在事件隊列中,等JavaScript主線程空閒了纔會去事件隊列中取出代碼放入主線程中去執行。定時器函數屬於異步事件,參數裏設置的時間並非延遲多少秒去執行回調函數,這個時間表明的是延遲多少秒把回調函數放入到異步事件隊列中,等到主線程空閒再被執行。這意味着至少要等這麼多時間後纔會執行回調函數。算法

一個例子:下面的代碼會輸出什麼結果?

 

for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 100 * i); } 結果是打印出10個10!解釋以下:setTimeout在若干毫秒後執行一個函數而且是在for循環結束後。for循環結束後,i的值爲10.因此當函數被調用的時候,它會打印出10! 若是想打印出1~9,有兩個方法,1,將var變成let關鍵詞(ES6纔開始支持)或者 2,使用當即執行函數捕捉每次循環的i的值。代碼以下: for (var i = 0; i < 10; i++) { (function(j){ setTimeout(function () { console.log(j); }, j * 10); })(i); }

 

 setInterval()函數的問題:假如設置了一個每隔100ms執行一次的定時器,第一次執行到該定時器時,會在100ms以後將回調函數加入到事件隊列中,再過100ms又會將這個回調函數加入到事件隊列中,而若是主線程在此期間一直沒有空閒,那麼事件隊列中的回調函數就一直不會被拿到主線程中取執行。可能出現的狀況就是主線程空閒的時候會一次性將這些回調函數同時執行而沒有任什麼時候間間隔。JavaScript引擎對此的處理辦法是:當使用setInterval()定時器時,只有當事件隊列中沒有該定時器的任何實例時,纔會將定時器中的回調函數加入到事件隊列中。 這確保了最小的時間間隔,可是引起的另外一個問題是可能 有些間隔 被跳過了。若是功能需求是每一個定時器函數都必須執行,那麼就不能知足需求了。因此通常都使用遞歸調用settimeout()定時器模擬setInterval()的效果。不會出現上面的兩個問題。

3, html標籤裏寫事件 傳 值

<select name="type" onchange="show_sub(this.options[this.options.selectedIndex].value)">    
    <option value="0">請選擇主菜名</option>    
    <option value="1">白菜</option>    
    <option value="2">蘿蔔</option>    
 </select> 
js代碼比較簡單 

<script>     
    function show_sub(v){     
        alert(v);     
    }     
</script>   

最重要的知識點是獲在select onchange時獲取option的value值: this.options[this.options.selectedIndex].value 

 4,JS中的"0" 是true仍是false

  if ('0') alert("'0' is true");

 if ('0' == false) alert("'0' is false");結果是,兩次都 alert 了!那麼 '0' 究竟是 true 仍是 false 呢?

答案是:在js作比較的時候,有這樣的三條規則: 
  • 若是比較的二者中有boolean,會把 boolean 先轉換爲對應的 number,即 0 和 1(false是0,1是true)
  • 若是比較的雙方中有一方爲number一方爲string,會把string轉換爲數字
  • 把string直接轉換爲boolean的時候,空字符串‘’轉換爲 false,除此外的一切字符串轉換爲 true 

5,瀏覽器兼容的enter事件 

<input type="text" id="text">
<script>
    document.getElementById("text").onkeypress = function(e) {
        e = e || window.event;
        key = e.keyCode || e.which || e.charCode;
        alert("按鍵碼: " + key + " 字符: " + String.fromCharCode(key));
    if (key == 13) {enter事件} };

6,JavaScript當即執行某個函數 深度思考  https://www.tangshuang.net/2020.html

幾種方式當即執行函數

在javascript中定義一個函數,而且當即去執行它。(這個狀況雖然看上去很瘋狂,可是實際上必定會用到,由於函數一旦執行完,內部的局部變量會被釋放,內存也釋放出來。)咱們可能第一種想到的方法是:

// 第一種
function a() {}
a();
沒錯,這個太簡單不過了。

固然,還有另一種相對高深的辦法:

window.onload = function() {}
這段代碼表示在網頁加載完以後當即執行function中的代碼,但這裏面隱含了另一層意思,也就是能夠把函數賦值給變量,使變量成爲一個其餘語言意義上的類。

// 第二種
var a = function(){}a();
不過這也給了咱們另一個思路:

function fun() {}
var a = fun();
a();
給咱們留下一個思考:

function(){}; // javascript語句中以function開始沒有實際的效果
一旦某條語句以function開始,這條語句沒辦法賦值給某個變量去執行它(說到這裏,函數名能夠能夠理解爲一個被賦值爲某個函數的變量而已)。

下面是真相的時候:

function a() {}
a();
若是函數名是一個被賦值的變量(也就是a),那麼爲什麼不將其實際的值替換掉變量名呢(也就是把a()替換爲function()())?因而,上面這段代碼變爲:

function(){}(); // 前面加粗部分表明a
可是在前面已經提到了,function開始的語句沒有實際的效果,所以,上面這個語句不會有實際效果。不只如此,這句代碼還會拋出錯誤提示:SyntaxError: Unexpected token。

此處括號的正確理解

形成上述這個異常的緣由是,javascript對語句的結束並非以;做爲標識,在這種普通狀況下,}被做爲語句結束的標識,所以,上述語句被解釋爲:

function(){};();
所以在執行()時,會拋出表達式錯誤。而若是咱們執行:

function(){};(1);
則不會出錯。緣由在於:語法正確。

我理解的(),在javascript中有兩種:一種是肯定優先級,另外一種是分組。固然,在聲明函數和函數使用的時候也會用到(),但這是一種語法,而不是運算。肯定優先級就是括號內的表達式先於括號外的表達式運算,例如:

1+(2*5)和(1+2)*5或(1+2)*(2+3)

而分組通常是在正則表達式中使用的概念,例如:

/<(.*)ok(this) is myhouse(.*)>/

在進行匹配的時候,上面的小括號將匹配結果分爲三組進行返回,在替換的時候,能夠對每一個組分別進行替換。所以,分組的概念,應該和本文沒有關係。所以,本文中的(),只有兩種理解,一種是運算符,一種是語法。

在上面的代碼中(1);中的();很明顯是一個運算符,括號內必須有表達式,不然就是語法錯誤。

咱們在回到上面的代碼,若是咱們給function加上()會怎樣?

(function(){});
恭喜你,你的函數初始化,雖然從結果上並無什麼卵用,並且和直接function(){}也沒有什麼不一樣,只不過是把function(){}提升了運算的優先級而已。

但是,當咱們執行下面的代碼的時候,狀況就大不相同了:

(function(){})();
代碼是從左往右執行的,就像a() || b();同樣若是a()爲真,就不執行b()了。一樣的道理,上面的代碼中,紅色部分做爲一個表達式,執行完畢,表明着一個函數已經初始化完畢,若是咱們回到:function(){}();,也就是前文拋出錯誤的那個語句你就會發現,神奇的事情發生了,紅色部分儼然就是咱們要的a,因此整個語句合起來也就是:a();,就這樣,函數被執行了。

在這條代碼中,第二個()再也不是運算符,而是函數的括號。而第一個(),則是一個運算符,提升了內部function的運算優先級,內部被優先執行,獲得結果後,與第二個()構成函數語法,執行了函數。

咱們再回頭來看()運算符的做用,來看一下下面這個代碼:

()();
這是一個神奇的代碼,世界上不會有任何程序員這樣去用,固然,它也會報錯。可是咱們如何正確去理解這種狀況呢?世界上是否存在下面這種javascript代碼:

(a+b)(c+d);
歷來沒有見過。若是世界上存在一種運算,就是沒有任何運算,那麼上面是成立的,可是,若是這種假設不成立的話,上面的代碼就是錯誤的。咱們歷來沒有見過(1+2)(3+4),雖然咱們小學的時候寫過這樣的算式,可是在代碼中是不存在的。

所以,咱們換一個思惟,不要只把它當作運算,而是運算和函數的結合呢?在你的瀏覽器中運行下面這段代碼試試:

(1+2)(3+4);// TypeError: (1 + 2) is not a function
提示的不是語法錯誤,而是數據類型錯誤,第二個括號 前面的不是一個函數。也就是說,第二個括號前面的,若是是函數類型,就正確了!那麼世界上有沒有一種算法,使運算後返回值爲函數呢?好比 fun1+fun2=fun3?好像我還歷來沒有遇到過,所以,想在第一個括號中構建一種運算使該代碼成立,還須要高高手來實現。惟一的解決辦法,就是在 第一個括號中委以函數,也就是(function(){})(3+4),而3+4不過僅僅是做爲前面這個函數的參數予以運行。

匿名函數的當即執行

當你覺得挖到寶藏的時候,下面的解釋或許讓你再一次開了腦洞。咱們提到function開頭的語句雖然初始化函數,可是函數並不被執行,其運行效果至關於什麼也沒發生。

爲了提交它的優先級,咱們再用一次()吧:

(function(){}());
此次,咱們直接把函數表達式和後面的()放在一個()裏面,這下子奇蹟也發生了,空號內部是一個表達式,表達式的意思就是}不表明結束,因此咱們前文提到的}表示語句結束的論斷不起做用了。()內部必須運算完成,才能結束此次表達式運算,因此上面代碼中的紅色部分又再次先運算了,運算完又和()組成了a(),因而,函數又執行了。

OK,咱們如今終於get到了終點:表達式必須運行完成,纔會結束表達式。這簡直就是天同樣的玄機,緊緊記住表達式這個概念以後,咱們再來看下面的幾個代碼:

!function(){}();
+function(){}();
-function(){}();
~function(){}();
……
沒錯,上面的!+-~,所有表明表達式,!表示非,~表示按位非。你能夠想出所有的表達式符號(固然必須得考慮運行是否合法,好比/0就不合法,分母不能爲0),從而實現上面的這個效果。

因而,咱們看到幾乎全部的插件,都會用上面的其中一種方式來定義整個代碼。

正是由於這個緣由,上面的全部代碼,均可以讓function(){}內部的代碼當即執行。

遺留問題:第二個括號內的參數

在多數插件中,咱們能夠看到以下的代碼:

!function(){}(jQuery);
基本上咱們都看懂了,可是第二個括號內有個jQuery表明什麼意思呢?

你想一下下面這個用法:

function a(var) {}
a(1);
而後把第二行的a替換爲function(var){},結果就變成了function(var){}(1);

沒錯,第二個括號內的值,是本來函數的特定參數。因此,上面那個jQuery的,咱們能夠將它還原爲:

var fun = function(a) {}
fun(jQuery);
就是這樣了。可是,jQuery是什麼呢?是一個對象啊!因此下面的代碼就來了:

!function($){
  // 在function中,$實際上就是jQuery,因此用$盡情玩耍吧。
}(jQuery);
難道你覺得到此就結束了嗎?不,看看下面的代碼:

!function(fun){}(function($){});
什麼鬼?你覺得我想表達什麼?其實,這是不少插件中的一種寫法,用以兼容不一樣的加載模式(CommonJS、CMD、CMD),具體是這樣的:

!function(fun){
  "use strict";
  if(typeof define === 'function' && define.amd) {   
    define(['jquery'], fun)
  } else {
    fun((typeof(jQuery) != 'undefined') ? jQuery : window.Zepto) 
  }
}(function($){
  "use strict";
  // 真正的插件代碼都在這裏
});
這是一個雙重傳值的過程。第一重,第一個function(fun)中的fun是第二個function($),所以,在第一個function中的代碼中fun($)和第二個function($)是等效的。第二重,第二個function($)中的$參數,是在第一個函數中進行傳遞過來的,第一個函數中,define(['jquery'],fun)和fun(jQeury)實際上在執行第二個函數,既然如此,真正的插件代碼就應該在第二個函數中去寫,第一個函數僅僅是經過多個判斷,返回正確的調用模式而已。

實際上,瞭解了上述以後,本文的題目是爲了當即執行某個函數,在實踐中,還有不少作法能夠在申請一個函數後當即執行它,好比:

(function(){}).call();
好了,這個問題就闡述到這裏,可能也有一些不足的地方,歡迎你們指正。
View Code

7, JavaScript中的數組或對象 循環方法總結

1, 普通for循環 [數組,對象] //注意,將長度賦給一個變量,防止每次循環都要算一下長度。for (var i=0, len=arr.length; i < len; i++){}

2, for in 【數組,對象】//注意 for (var i in arr){} 中的i類型始終是string類型的,有時候須要int類型時要注意。

3, array.forEach(function(value, index){})【數組】// ES5推出的數組自帶的循環,主要功能是遍歷數組,實際性能比for 還弱。forEach這種方法也有一個小缺陷:你不能使用break語句中斷循環,也不能使用return語句返回到外層函數

4,array.map(functino(value, index){})【數組】//也是ES5推出的,支持return 語句

5,for ... of 【數組】//ES6新增功能

6,jQuery的靜態方法$.each(array/obj, function(index, value){})

7, underScoreJS中的方法:_.each(array/obj, function(index, value){})

8, 關於 jQuery的 tmpl 模板插件的說明

 

var html = $("#menu_tmpl").tmpl({data:retval.data}).outerHTML();
$("#phpNav").html(html);
使用tmpl()方法時,必定要用對象模式,不容易出問題! (自己這裏的參數只能是對象格式,而不能是數組)

5

5

5

5

5

5

5

5

相關文章
相關標籤/搜索