定義和用法:javascript
continue 用於跳過循環中的一個迭代,並繼續執行循環中的下一個迭代。前端
continue 與 break 語句的區別是:break 是結束整個循環體,continue是結束單次循環。java
可是,在執行 continue 語句時,表現出了兩種不一樣類型的循環:web
在 while 循環中,會先判斷條件,若是條件爲 true,循環再執行一次。正則表達式
在for循環中,自增加表達式(如:i++)會先計算,而後再判斷條件是否爲true,再決定是否執行迭代。算法
continue 語句可應用於可選的標籤引用。編程
注意: continue 語句(不帶標籤引用),只能用在循環或 switch 中。數組
循環代碼塊,在 i 的值等於 "3" 時跳過當前循環:瀏覽器
定義和用法:閉包
循環代碼塊,break在變量 i 爲 "3" 時退出循環:
break 語句用於退出 switch 語句或循環語句(for, for ... in, while, do ... while)。
當 break 語句用於 switch 語句中時,會跳出 switch 代碼塊,終止執行代碼。
當 break 語句用於循環語句時,會終止執行循環,並執行循環後代碼(若是有的話)。
break 語句一樣可用於可選的標籤引用,用於跳出代碼塊。
注意: break 語句(不帶標籤引用),只能用在循環或 switch 中。
定義和用法:
arguments是函數裏的 | 能夠經過數組下標的形參訪問函數實參值 |
arguments對象 | 沒有表示參數集合,而是一個僞類數組 |
arguments對象是 | 全部(非箭頭)函數中均可用的局部變量 |
此對象包含傳遞給函數的每一個參數 | 第一個參數在索引0處。 |
你可使用arguments對象在函數中引用函數的參數。 |
例如,若是一個函數傳遞了三個參數,你能夠以下方式引用他們:
arguments[0]
arguments[1]
arguments[2]
求平均值:
function avg() { var num = 0, j = 0; for (let i = 0; i <= arguments.length; i++) { if (typeof arguments[i] != 'number') continue; num += arguments[i]; j++; } num /= 1; return num; } document.write(avg(1, 2, 3, 4));
它若是和callee屬性一塊兒使用的話,利用它能夠設計函數迭代操做。使用arguments.callee能夠獲取匿名函數。最後比較實參和形參的
個數以檢測用戶傳遞的參數是否符合要求。若是不是匿名函數的話,則arguments.callee等價於函數名(f());
語法:
[function.]arguments.callee
可選項 function 參數是當前正在執行的 Function 對象的名稱。
說明:
callee 屬性的初始值就是正被執行的 Function 對象。
callee 屬性是 arguments 對象的一個成員,是arguments的屬性,該屬性是一個指針,指向擁有arguments對象的函數,這有利於匿
名函數的遞歸或確保函數的封裝性,例以下邊示例的遞歸計算1到n的天然數之和。而該屬性僅當相關函數正在執行時纔可用。更有須要注意
的是callee擁有length屬性,這個屬性有時候用於驗證仍是比較好的。arguments.length是實參度,arguments.callee.length是形參長
度,由此可以判斷調用時形參長度是否和實參長度一致。
function calleeDemo() { alert(arguments.callee); }
throw 語句容許咱們建立自定義錯誤。正確的技術術語是:建立或拋出異常(exception)。
若是把 throw 與 try 和 catch 一塊兒使用,那麼您可以控制程序流,並生成自定義的錯誤消息。異常能夠是 JavaScript 字符串、數字、
邏輯值或對象。
throw new Error('傳遞的參數不匹配');
search() 方法 | 用於檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串 |
search() 方法 | 執行正則表達式和 String 對象之間的一個搜索匹配 |
當你想要知道字符串中是否存在某個模式(pattern)時可以使用 search(),相似於正則表達式的 test() 方法。當要了解更多匹配信息
時,可以使用 match()(但會更慢一些),該方法相似於正則表達式的 exec() 方法。
語法:
stringObject.search(regexp)
參數 |
描述 |
regexp |
該參數能夠是須要在 stringObject 中檢索的子串,也能夠是須要檢索的 RegExp 對象。 註釋:要執行忽略大小寫的檢索,請追加標誌 i。 |
返回值
stringObject 中第一個與 regexp 相匹配的子串的起始位置。
註釋:若是沒有找到任何匹配的子串,則返回 -1。
說明:
search() 方法不執行全局匹配,它將忽略標誌 g。它同時忽略 regexp 的 lastIndex 屬性,而且老是從字符串的開始進行檢索,這
意味着它老是返回 stringObject 的第一個匹配的位置。
特別說明:
字符串中字符的位置與數組相似,都是從0開始的。
searchValue不但能夠是普通字符串,也能夠是正則表達式,
function isEmail() { if (arguments.length > 1) { throw new Error('你只能傳遞一個參數'); } var regexp = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/; if (arguments[0].search(regexp) != -1) { return true; } else { return false; } } var email = '13021946513@qq.com'; if (isEmail(email)) { document.write(email); } else { document.write('請您從新輸入郵箱地址'); }
獲取函數的實參個數:使用arguments對象的length屬性,僅可以在函數體內使用。
獲取形參的個數使用函數名.length或者a.callee.length,function對象的length屬性在函數體內外均可以使用.
function check(a) { if (a.length != a.callee.length) { throw new Error('參數不一致'); } }
function f(a, b, c, d) { check(arguments); return (a + b + c + d) } document.write(f(3, 4))
用戶能夠經過點語法爲函數定義靜態屬性和方法。
函數屬性能夠在函數體內定義,只能在內部調用;函數屬性也能夠在函數體外定義,在外部調用。
函數方法能夠在內部或外部定義,無論在內部或外部定義均可以調用此函數方法。
用戶不妨爲函數定義屬性,而後利用函數屬性實現函數每次返回低增值。
function f() { return f.x++; } f.x = 0; for (var i = 0; i < 10; i++) { document.write(f()); }
call()和apply()是function對象的原型方法。把一個函數當作一個方法綁定到指定對象上並進行調用。
具體用法以下:
function.call(thisobj,args...)
function.apply(thisobj,args)
其中參數thisobj表示指定的對象,參數args表示要傳遞給被調用函數的參數。而call()方法只能接受多個參數列表,apply()只能接受一個數組
或僞數組,數組元素將做爲參數傳遞給被調用的函數。
代碼以下:
function f(x, y) { return x + y; } function o(a, b) { return a * b; } document.write(f.call(o, 3, 4));
使用call()和apply()方法能夠把一個函數轉換爲指定對象的方法,並在這個對象上臨時綁定調用該方法。
提示:它們可以動態改變函數內this指代的對象,這在面向對象編程中是很是有用的。
call()和apply()傳遞給參數的方式不一樣,
apply()是以數組形式傳遞參數,
call()方法以多個值的形式傳遞參數。
代碼以下:
function r(x) { return (x); } function f(x) { x[0] = x[0] + '>'; return x; }
function o() { var temp = r; r = function () { return temp.apply(this, f(arguments)); } }
function a() { o(); document.write(r('=')); } for (var i = 0; i < 10; i++) { a(); }
函數function增長了一個原型方法bind(),是指用來把函數綁定到指定對象上。
具體用法以下:
function.bind(thisArg[,arg1[,arg2[,argN]);
參數說明以下:
function |
必須參數,一個函數對象 |
thisArg |
必須參數,this關鍵字可在新函數中引用的對象 |
arg1[,arg2[,argN]] |
可選參數,要傳遞到新函數的參數的列表。 |
bind方法將返回與函數相同的新函數不會當即執行,等須要的時候纔會執行該新函數。bind()方法也能夠多個或兩個傳遞參數值。
var displayArgs = function (val1, val2, val3, val4) { document.write(val1 + '<br> ' + val2 + ' <br>' + val3 + '<br> ' + val4 + '<br> '); }
var emptyObject = {}; var displayArg2 = displayArgs.bind(emptyObject, '姓名:' + '張亮', '年齡:' + 25 + '歲'); displayArg2('身高:' + 180 + 'cm', '民族:' + ' ' + '漢族');
語法:
string.trim()
定義和用法:
trim() |
方法用於刪除字符串的頭尾空格。 |
trim() |
方法不會改變原始字符串。 |
實例:
去除字符串的頭尾空格:
function myTrim(x) { return x.replace(/^\s+|\s+$/gm,''); }
function myFunction() { var str = myTrim(" Runoob "); alert(str); }
this的定義:
this是函數體內自帶的一個對象指針,this指向當前調用函數的那個對象,或者指向類的當前實例。
this的特色:
在function內部被建立
指向調用時所在函數所綁定的對象(拗口)
this 不能被賦值,但能夠被 call/apply 改變
this的用途:這裏把它全部用到的地方列出
function Tab(nav, content) { this.nav = nav this.content = content } Tab.prototype.getNav = function() { return this.nav; };
2. this 和對象
var tab = { nav: '', content: '', getNav: function() { return this.nav; }, setNav: function(n) { this.nav = n; } }
3. this 和函數
function showMsg() { alert(this.message) } var m1 = { message: '輸入的電話號碼不正確' } var m2 = { message: '輸入的身份證號不正確' } showMsg.call(m1) // '輸入的電話號碼不正確' showMsg.call(m2) // '輸入的身份證號不正確'
4. 全局環境的 this
var x = 10; function func() { alert(this.x) } var obj = { x: 20, fn: function() { alert(this.x) } } var fn = obj.fn func() // 10 fn() // 10
沒錯,最終輸出的都是全局的10。永遠記住這一點:判斷 this 指向誰,看執行時而非定義時,只要函數(function)沒有綁定在對象上調用,它的
this就是window。
5. this 和 DOM/事件
<div id="nav" onclick="getId()">ddd</div>
<script>
function getId() { alert(this.id) }
</script>
點擊 div 後,爲何 id 是 undefined,不說是指向的當前元素 div 嗎?若是記住了前面提到的一句話,就很清楚爲啥是 undefined,把這句話再貼出來。判斷 this 指向誰,看執行時而非定義時,只要函數(function)沒有綁定在對象上調用,它的 this 就是 window。
這裏函數getId調用時沒有綁定在任何對象上,能夠理解成這種結構:
div.onclick = function() { getId() }
getId 所處匿名函數裏的 this 是 div,但 getId 自身內的 this 則不是了。固然 ES5 嚴格模式下仍是有個坑。
6. this 能夠被 call/apply/bind 改變
var m1 = { message: 'This is A' } var m2 = { message: 'This is B' } function showMsg() { alert(this.message) } showMsg() // undefined showMsg.call(m1) // 'This is A' showMsg.call(m2) // 'This is B'
7. me/self/that/_this 暫存 this
若是採用 OOP 方式寫 JS 代碼,無可避免的會用到 this,方法內會訪問類的內部屬性(字段),也可能會調用類的另外一個方法。當類的方法內又有一個 function 時,好比瀏覽器端開發常常碰見的給 DOM 元素添加事件,這時若是事件處理器(handler)中的想調用類的一個方法,此時 handler 內的 this 是 dom 元素而非類的當前對象。這個時候,須要把 this 暫存,開發者發揮着本身的聰明才智留下了幾種經典的命名 me, self, that, _this。
如:通常會在每一個方法的第一句就把 this 暫存下來。
8. ES5 中新增的 bind 和 this
var modal = { message: 'This is A' } function showMsg() { alert(this.message) } var otherShowMsg = showMsg.bind(modal) otherShowMsg() // 'This is A'
bind 只是 call/apply 的高級版,其它沒什麼特殊的。
9. ES6 箭頭函數(arrow function) 和 this
var book = { author: 'John Resig', init: function() { document.onclick = ev => { alert(this.author) ; // 這裏的 this 不是 document 了 } } }; book.init()
對象 book 裏有一個屬性 author, 有一個 init 方法, 給 document 添加了一個點擊事件,若是是傳統的函數,咱們知道 this 指向應該是 document,但箭頭函數會指向當前對象 book。
箭頭函數讓 JS 迴歸天然和簡單,函數定義在哪它 this 就指向哪,定義在對象裏它指向該對象,定義在類的原型上,就指向該類的實例,望文知意這樣更容易理解。
總結:
函數的上下文 this 是 JS 裏不太好理解的,在於 JS 函數自身有多種用途。目的是實現各類語言範型(面向對象,函數式,動態)。this 本質是和麪向對象聯繫的,和寫類,對象關聯一塊兒的, 和「函數式」沒有關係的。若是你採用過程式函數式開發,徹底不會用到一個 this。 但在瀏覽器端開發時卻無可避免的會用到 this,這是由於瀏覽器對象模型(DOM)自己採用面向對象方式開發,Tag 實現爲一個個的類,類的方法天然會引用類的其它方法,引用方式必然是用 this。當你給DOM對象添加事件時,回調函數裏引用該對象就只能用 this 了。
閉包是Js的重要特性之一,在程序中有相當重要的做用。
Js函數可以記住本身定義時所處的做用域,即便函數不在此做用域運行,依然能夠訪問此做用域中的變量。
閉包函數就是嵌套結構的函數。
閉包函數須要知足下面3個條件:
① 在一個函數(含有私有變量或局部變量)內定義的一個函數。也就是嵌套。
② 內部函數應該訪問外部函數中聲明的私有變量、參數或其餘內部函數。
③ 若是在外部函數外調用這個內部函數,它就成爲了閉包函數。
下面是一個經典閉包結構:
function f(x) { var a = x; var c=1; var b = function () { return a;//造成一個閉包 }; a++; return b; } var c = f(5); document.write(c());
------------------------
若是沒有閉包函數的做用,這種數據寄存和傳遞沒法實施:
function f(x) { var a = x; var b = a; a++; return b; } var c = f(5); document.write(c);
當該函數時(f())無論是數字幾賦值給c後進行調用,該是多少就是多少這個‘數’,不能實時監測這個變量的變化。
注意:一但函數被調用執行,則閉包體也會隨之誕生。
閉包函數被再次執行或者經過某種方法進入函數體時,就能夠獲取閉包函數內包含的信息。
簡單的描述:閉包能夠說是函數的數據包、存儲數據。這個數據包在函數執行過程當中始終處於激活狀態,只有調用函數閉包才能生效。當函數調用返回以後,閉包保存下來與內部函數關聯的變量的動態聯繫(幫助監測)。
下面是閉包和閉包的經常使用場景:
做用域(受javascript鏈式做用域結構的影響,父級變量中沒法訪問到子級變量的值,爲了解決這個問題,才使用的閉包。)閉包就是可以讀取其餘函數內部變量的函數。(在JS中,只有函數內部的子函數才能讀取局部變量,所以能夠把閉包簡單理解爲」定義在一個函數內部的函數」。不管是在事件中,for循環中,仍是在函數自調用中,只要return出來,便有閉包的應用)。
閉包會把函數中變量的值保存下來,供其餘函數使用,這些變量會一直保存在內存當中,這樣佔用大量的內存,使用不當極可能形成內存泄漏,故要及時清除,清楚方法有兩種,一是標記清除,二即是引用計數清除。
閉包的經常使用場景有一是函數做爲返回值,二是函數做爲參數來傳遞。不適用於返回閉包的函數是個特別大的函數,不少高級應用都要依靠閉包實現.
使用閉包的好處是不會污染全局環境,方便進行模塊化開發,減小形參個數,延長了形參的生命週期,壞處就是不恰當使用會形成內存泄漏。
下面經過幾個示例介紹閉包的簡單使用,更直觀的理解什麼是閉包以及閉包的函數的做用和用法。
用法1:使用閉包結構可以跟蹤動態環境中的實時變化,並即時存儲。
function f() { var a = 1; Var b = function () { return a; } a++; Return b; } var c=f(); document.write(c());
用法2:閉包不會由於外部函數環境的註銷而消失,而是始終存在。
function f() { var a = 1; b = function () { alert(a); } c = function () { a++; } d = function (x) { a = x; } } <button onclick="f()">按鈕1:(f())</button><br> <button onclick="b()">按鈕2:(b=function(){alert(a);})()</button><br> <button onclick="c()">按鈕3:(c=function(){a++;})()</button><br> <button onclick="d(100)">按鈕4:(d=function(x){a=x;})(100)</button><br>
用法3:如何利用閉包存儲變量全部變化的值。
function f(x) { var a = []; for (var i = 0; i < x.length; i++) { var temp = x[i]; a.push(function () { document.write(temp + ' ' + x[i]) }); } return a; } function e() { var a = f(['a', 'b', 'c']); for (var i = 0; i < a.length; i++) { a[i](); } } e();
閉包常見的用法就是爲要執行的函數提供參數。
好比:
爲事件屬性傳遞動做 |
爲定時器函數傳遞行爲等 |
這在web前端中很是常見的一種應用。
用法1:
function f(a, b) { return function () { a(b); } } var c = f(alert, '愛前端'); var d = setTimeout(c, 1000);
閉包其實還能夠用於建立額外的做用域,經過該做用域就能夠設計動態數據管理器。
用法2:下面的例子如何使用閉包做爲值來進行傳遞。
function f(a, b) { return function () { a(b); } } var c = f(alert, '我在家學習和鍛鍊!'); window.onload = c;
用法3:下面經過閉包可使做爲緩衝器的數組與依賴它的函數關聯起來。實施優雅的打包。
var f = function () { var a = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]; return function (a1, a2, a3, a4, a5) { a[0] = a1; a[1] = a2; a[2] = a3; a[3] = a4; a[4] = a5; return a.join(','); }; }(); var a = f(12, 14, 16, 18, 20); var b = f(11, 13, 15, 17, 19); document.write(a + '<br>'); document.write(b + '<br>');
不少時候咱們但願引用一個函數後能暫停執行,由於在複雜的環境中不等到執行的時候是很難知道具體參數的,而先前被引用時更是沒法預知所要傳遞的參數。
下面用法:但願爲頁面中特定的元素或標籤綁定幾個事件,使其可以在鼠標通過、鼠標移開和鼠標單擊時呈現不一樣的背景顏色。
<p>p1</p><p>p2</p><p>p3</p>
<script>
function f(o, m) { return function (e) { e = e || window.event; return o[m](e, this); } } function g(id) { return function () { var e = document.getElementsByTagName(id); if (e) { for (var i in e) { e[i].onclick = f(g, 'click'); e[i].onmouseover = f(g, 'over'); e[i].onmouseout = f(g, 'out'); } } } } g.click = function (event, element) { element.style.backgroundColor = 'red'; } g.over = function (event, element) { element.style.backgroundColor = 'orange'; } g.out = function (event, element) { element.style.backgroundColor = 'green'; } window.onload = g('p');
</script>
函數綁定就是爲了糾正函數的執行上下文,特別是當函數中帶有this關鍵字的時候,這一點尤爲重要,稍微不當心,就會使函數的執行上下文發生跟預期不一樣的改變,致使代碼執行上的錯誤。
函數綁定具備3個特徵:
函數綁定要建立一個函數,能夠在特定環境中以指定參數調用另外一個函數。 |
一個簡單的bind()函數接受一個函數和一個環境,返回一個在給定環境中調用給定函數的函數 |
而且將全部參數原封不動的傳遞過去。 |
被綁定函數與普通函數相比有更多的開銷,它們須要更多內存,同時也由於多重調用而稍微 慢一點,因此最好只在必要時使用。 |
var handler = { messge: '學習js語言', handlerClick: function (event) { document.write(this.messge); } }; var btn = document.getElementsByTagName('my-btn'); EventUtil.addHandler(btn, 'clck', bind(handler.handlerClick, handler));
由於 jQuery 庫的緣故,(Jquery最大的亮點就是它的鏈式語法)鏈式語法在前端界變得很是流行。實際上這是一種很是容易實現的模式。基本上,你只須要讓每一個函數返回 'this',這樣其餘函數就能夠當即被調用,它也是點語法。
下面用法:
Function.prototype.method = function (name, func) { if (!this.prototype[name]) { this.prototype[name] = func; return this; } }; String.method('trom', function () { return this.replace(/^\s+|\s+$/g, ''); }); String.method('writeln', function () { document.write(this); return this; }); String.method('alert', function () { console.log((this)); return this; }); var str = '黃靜遠'; str.trim().writeln().alert();
函數節流的設計思想就是讓某些代碼能夠在間斷狀況下連續重複執行。實現的方法是使用定時器對函數進行節流。
下面用法:
function throttle(method, context) { clearTimeout(method.tId); method.tId = setTimeout(function () { method.call(context); }, 100); }
須要注意的一點:函數的節流是經過減小實際邏輯處理過程的執行來提升事件處理函數運行性能的手段,並無實質上減小事件的觸發次數。
柯里化又稱爲部分求值,柯里化是把接受多個參數的函數變換成接收一個單一的參數的函數。而且返回一個新函數。而這個函數新函數可以接收原函數的參數。
下面用法:
function add(a) { // 瘋狂的回調 return function(b) { return function(c) { return function(d) { // return a + b + c + d; return [a, b, c, d].reduce(function(v1, v2) { return v1 + v2; }); } } } } console.log(add(1)(2)(3)(4)); // 10
柯里化有3個常見做用:
參數複用
提早返回
延遲計算/運行
遞歸是函數對自身的調用。遞歸作爲一種算法在程序設計語言中普遍應用。
一個過程或函數在其定義或說明中有直接或間接調用自身的一種方法,它一般把一個大型複雜的問題層層轉化爲一個與原問題類似的規模較小的問題來求解,
遞歸策略只需少許的程序就可描述出解題過程所須要的屢次重複計算,大大地減小了程序的代碼量。
遞歸的能力在於用有限的語句來定義對象的無限集合。
通常來講,遞歸須要有邊界條件、遞歸前進段和遞歸返回段。當邊界條件不知足時,遞歸前進;當邊界條件知足時,遞歸返回。
遞歸算法解決問題的特色:
遞歸就是方法裏調用自身。
在使用遞增歸策略時,必須有一個明確的遞歸結束條件,稱爲遞歸出口。
遞歸算法解題一般顯得很簡潔,但遞歸算法解題的運行效率較低。因此通常不提倡用遞歸算法設計程序。
在遞歸調用的過程中系統爲每一層的返回點、局部量等開闢了棧來存儲。遞歸次數過多容易形成棧溢出等,因此通常不提倡用遞歸算法設計程序。
任何有意義的遞歸老是兩部分組成的:
遞歸調用 |
遞歸終止條件 |
遞歸運算在無限制的狀況下,會無休止地自身調用。顯然,程序不該該出現這種無休止的遞歸調用,而只應出現有限次數的有終止的調用。
爲此通常在遞歸運算中結合if語句來進行控制。
遞歸算法的特色:
在函數過程當中調用自身。
在遞歸過程當中,必須有一個明確的條件判斷遞歸的結束,既遞歸出口。
遞歸算法簡潔但效率低,一般不做爲推薦算法。
用法1 :看電影不知道在第幾排,看電影時不清楚本身在第幾排,能夠經過問前一排的人來得知,進行加1便可。
function fn = (n) { if(n< = 0) return '座位不存在' if(n>1) { return fn(n-1)+1 } else { return 1 } }
用法2 :走格子有多少走法,一共有n格,每步能夠走1格或者2格,問一共有多少走法。
首先分解問題是第n格能夠是前面n-1格走的,也多是n-2格走的。因此fn(n) = f(n-1) + f(n-2)。
也要知道終止條件是隻有1步,那麼只有一步的可能狀況是還有1格,也多是還有2格。
function fn = (n){ if(n>2){ return fn(n-1) + fn(n-2) } else if(n==2) { return 2 } else { return 1 } }