JavaScript知識點總結(一)

是時候把JS的知識點總結下,而且會持續施工,每一個知識點若是有更深刻的技術探討和知識會陸續添加進去。javascript


ECMAScirpt中的變量,函數名,操做符都區分大小寫。java

標識符

標識符指的多是:express

  • 變量名數組

  • 函數名瀏覽器

  • 屬性名安全

  • 函數的參數app

標識符的名稱:less

  • 第一個字符只能是字母,下劃線_,或者美圓符號$;函數

  • 其餘的能夠是字母,數字,下劃線_,或者美圓符號$。oop

  • 按照慣例,標識符名稱應使用駝峯法,即首字母小寫,剩下的每一個單詞首字母大寫。

  • 不能把關鍵字、保留字、TRUE、FALSE、NULL做爲標識符名稱。

註釋:

//單行註釋

/*
多行註釋
多行註釋
*/

嚴格模式:

ES5引入了嚴格模式,嚴格模式下,某些舊版本(ES3)的一些不肯定行爲將獲得處理,而對某些不安全的操做也會拋出錯誤。支持嚴格模式的瀏覽器:IE10+ Firefox 4+ Safari 5.1+ Opera 12+ Chrome

//在整個腳本中引入嚴格模式,則在script標籤頂部或者*.js文件頂部添加以下代碼便可。
"use strict";

//在指定函數中引入嚴格模式:
function f1(){
     "use strict";
     //TODO...
};

TODO : 引入了嚴格模式與沒引入嚴格模式的js文件如何解決衝突以及共存?

語句:

ES中的語句以一個分號結尾,省略分號雖然有效但不推薦。

var sum = 1 + 2;

關鍵字與保留字:

// 關鍵字
break case catch continue debugger default delete do instanceof else new finally return for switch function this if throw in try typeof var void while with
// ES3定義的保留字
abstract boolean byte char class const debugger double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile

//ES5中非嚴格模式下的保留字縮減爲這些:
class enum extends super const export import

//ES5中嚴格模式下的相對非嚴格模式增長的保留字,其中let與yield是新增的。
implements interface let package private protected public static yield
//實際開發中,建議將ES3定義的保留字外加新增的let與yield做爲參考。

須要注意的是,ES5的嚴格模式下,evalarguments也不能做爲標識符與屬性名,不然會拋出錯誤。

變量:

ES中的變量是鬆散類型的,即變量能夠保存任何類型的數據。
定義變量使用var操做符,後跟變量名(即一個標識符),
使用var操做符定義的變量會成爲該做用域下的局部變量,該變量在函數退出以後就會被銷燬:

var a; //定義一個名爲a的變量,值是undefined
var b = null; //定義一個名爲b的變量,值爲null(空)
var c = 'percy'; //定義一個名爲c的變量,值爲字符串「percy」
function f1(){
  var name = 'jon'; //函數f1()下的局部變量
  alert(name); 
}
f1(); //jon
alert(name); //外部不能直接訪問函數的內部變量
//使用一條語句定義多個變量,用逗號分隔便可。
var name='jon', age=25, isMarried=false;

數據類型:

ES中有
5種簡單數據類型(基本數據類型):UndefinedNullBooleanNumberString
1種複雜數據類型:Object


檢測給定變量的數據類型 —— typeof操做符

返回值:

  • undefined——給定的值未定義;

  • boolean——給定的值是布爾值;

  • string——給定的值是字符串;

  • number——給定的值是數值;

  • object——給定的值是對象或者null

  • function——給定的是函數;

function f2(){
    console.log('Hi!');
}
var name = 'jon';
var age = 25;

alert(typeof f2); //function
alert(typeof name); //string
alert(typeof age); //number

ES數據類型之 Undefined 類型

只有一個值:undefined

var name; 
/*var name = undefined;*/ //無需把變量顯式設置undefined值
alert(name == undefined); //true

變量的值爲undefined與未聲明的變量並不同,但使用typeof操做符均會返回undefined,但輸出值時未聲明的變量會產生錯誤:

var job; //該變量已聲明但未賦值,默認值爲undefined
// var name2; 該變量並未聲明

alert(typeof job); //測試變量類型,輸出undefined
alert(typeof name2); //測試變量類型,即便變量未聲明也會輸出undefined

//輸出值時
alert(job); //undefined
alert(name2); //產生錯誤:Uncaught ReferenceError: name2 is not defined

ES數據類型之 Null 類型

只有一個值:null
undefined值派生自null值,因此用==測試二者時會返回true
null值表示一個空對象指針,因此使用typeof操做符時會返回object
若是建立的變量未來用於保存對象,那麼初始聲明該變量時應把值設置爲null

var name = null;
alert(typeof name); //object

ES數據類型之 Boolean 類型

有兩個值:truefalse

//注意Boolean類型字面值是區分大小寫的,True、False以及其餘大小寫混合的形式均不屬於Boolean類型值;
var isBoy = true;
var isGirl = false;
使用Boolean()函數把其餘值轉爲Boolean值
var name = 'jon';
var nameBool = Boolean(name); //true

轉換規則以下表:

數據類型 轉爲true的值 轉爲false的值
Boolean true false
String 任何非空字符串 ""(空字符串)
Number 任何非零數值(包括無窮大) 0,NaN
Object 任何對象 null
Undefined 不適用 undefined

轉換規則對於流程控制語句自動執行相應的Boolean轉換很是重要:

var name = 'jon';
if(name){ //name轉換爲true,執行下面的語句
    alert('name is defined!');
}

ES數據類型之 Number 類型

包含整數浮點數(雙精度數值)NaN

整數
var intN1 = 123; //十進制整數
var intN2 = 013; //十進制的11
var intN3 = 018; //無效的八進制,會被轉成十進制的18,而且在嚴格模式下回拋出錯誤
var intN4 = 0xB; //十六進制,會被轉爲十進制的11
alert(-0 == +0); //true,ES中正零相等於負零;
浮點數
var fN1 = 0.1;
var fN2 = 1.1;
var fN3 = .1; //不推薦
var fN4 = 1. //被解析爲整數1
var fN5 = 1.0; //被解析爲整數1
var fN6 = 1.05e5; //e表示法,即科學記數法,會被解析成105000,即1.05乘以10的7次方
var fN7 = 3e-6; //會被解析成0.000003

浮點數的精確度遠遠不如整數,因此永遠不要用計算浮點數來進行條件測試:

if(a + b = 0.3){ //不要作這樣的測試!
    //DO STH...
}
數值範圍
console.log(Number.MIN_VALUE); //ES能表示的最小數,結果是5e-324
console.log(Number.MAX_VALUE); //ES能表示的最大數,結果是1.7976931348623157e+308
/*
若一次運算中,計算結果超過了ES的最大或最小數,那麼這個結果會被轉換成特殊的Infinity或-Infinity,該值沒法參與運算;如下兩個屬性也保存着上述兩個值;
*/
alert(Number.NEGATIVE_INFINITY); //-Infinity
alert(Number.POSITIVE_INFINITY); //Infinity

肯定某個結果是否爲有窮的(是否位於ES能表示的最大與最小數之間的有效數值),使用isFinite()函數;

var a = 10.4e-8;
alert(isFinite(a)); //true,該數值在有效範圍以內
NaN (Not a Number,非數值(中文名字)是一個特殊的數值)

用於表示一個原本要返回數值的操做數沒有返回數值的狀況,這樣就不會拋出錯誤;

  • ES中0除以0都會返回NaN;(其餘數值除以0會返回Infinity或者-Infinity)

  • 任何涉及NaN的運算操做也會返回NaN;

  • NaN不等於任何值,包括它本身;

alert(NaN == NaN); //false

isNaN()函數,接受一個參數,肯定該參數是否「不是數值」,若是該參數是數值或者能轉換成數值,則會返回false,不然返回true

alert(isNaN(1)); //false
alert(isNaN('2')); //false,能夠把字符串2轉換成數值2
alert(isNaN(true)); //false,能夠把布爾值true轉換成數值1,若是false則轉換成0
alert(isNaN('1024cl')); //true,數值與字符串不能轉換成數值
alert(isNaN('true')); //true,字符串*均*不能轉換成數值
alert(isNaN(NaN)); //true,NaN自己不是有效的數值
數值轉換,有三個方法,Number()parseInt()parseFloat()

Number()的轉換例子:

alert(Number(1)); //1
alert(Number(true)); //轉換成1
alert(Number(false)); //轉換成0
alert(Number(null)); //轉換成0
alert(Number(undefined)); //NaN
alert(Number("")); //空字符串轉換成0
alert(Number("12")); //轉換成12
alert(Number("034")); //忽略前導0,轉換成34
alert(Number("12ab")); //NaN
alert(Number("0x11")); //有效的十六進制會轉換成十進制的17

更經常使用的parseInt()parseFloat()例子:

alert(parseInt(1)); //1
alert(parseInt(11.91)); //11
alert(parseInt(true)); //NaN
alert(parseInt(false)); //NaN
alert(parseInt(null)); //NaN
alert(parseInt(undefined)); //NaN
alert(parseInt("")); //NaN
alert(parseInt("12")); //12
alert(parseInt("034")); //34
alert(parseInt("12ab")); //忽略數值後的無效字符,轉換爲12
alert(parseInt("ab12")); //NaN
alert(parseInt("0x11")); //17
//在轉換八進制的字符串包含的數值中,ES3與ES5有時會存在分歧:
alert(parseInt("067")); //ES3中會輸出55
alert(parseInt("067")); //ES5中會忽略前導0,並轉換成10進制的67

基於上面的問題,做爲最佳實踐,使用parseInt()始終應該加入第二個參數,即須要轉換時須要使用的進制數

alert(parseInt("076",8)); //62
alert(parseInt("076",10)); //76
alert(parseInt("0xAA",16)); //170
alert(parseInt("AA",16)); //170
alert(parseInt("AA")); //NaN
//parseFloat()只會解析十進制數值,因此沒有第二個參數
alert(parseFloat("1.2.3")); //只會解析左起第一個小數點,因此該數值會被轉換成1.2
alert(parseFloat("0xAA")); //十六進制數值始終會被轉換成0
alert(parseFloat(11.1)); //11.1
alert(parseFloat("443abc")); //443,忽略後面的無效字符
alert(parseFloat("443.3aa")); //443.3,忽略後面的無效字符
alert(parseFloat("3.33e7")); //33300000
alert(parseFloat("0757.2768")); //忽略前導0,757.2768

ES數據類型之 String 類型

即字符串,由0或多個16位Unicode字符組成的字符序列;

//能夠由單引號或雙引號包裹,且左右引號必須匹配
var s1 = 'name1'; 
var s2 = "name2";
字符字面量

String數據類型包含一些特殊的字符字面量,也叫轉義序列,用於表示非打印字符,或者有其餘用途的字符:

字面量 含義
n 換行
t 製表
b 空格
r 回車
f 進紙
\ 斜槓
' 單引號('),在用單引號表示的字符串中使用,例如'I 'm JonHo'
" 雙引號("),在用雙引號表示的字符串中使用,例如"I "m JonHo"
xnn 以十六進制代碼nn表示的一個字符,其中n爲0~F,例如,x41表明A
unnnn 以十六進制代碼nnnn表示的一個Unicode字符,其中n爲0~F,例如,u03a3表示希臘字符∑

上述的字符字面量能夠出如今字符串的任意位置,而且也會被做爲字符來解析:

var sign = "sign is : \u011f";
console.log(sign);  /*sign is : ğ*/
console.log(sign.length); //11,說明六個字符長的轉義序列只會表示一個字符,佔一個索引位置;
轉換爲字符串的方法toString():
var name = 'Jon';
alert(name.toString()); //"Jon"
var age = 25;
alert(age.toString()); //字符串"25"
var isMarried = false;
alert(isMarried.toString()); //字符串"false"

//null與undefined沒有toString()方法
alert(null.toString()); //NaN
alert(undefined.toString()); //NaN

//轉換數值的狀況下,能夠傳入一個參數,即輸出數值的基數
var num = 10;
alert(num.toString()); //默認十進制輸出,10
alert(num.toString(2)); //二進制輸出,1010
alert(num.toString(8)); //八進制輸出,12
alert(num.toString(10)); //十進制輸出,10
alert(num.toString(16)); //十六進制輸出,A

在不知道轉換的值是否爲nullundefined的狀況下,可使用轉型函數String(),該函數能把任何類型的值轉爲字符串:

  • 若是傳入的值有toString()方法,則調用該方法並返回相應的結果;

  • 若是傳入的值是null,則返回"null";

  • 若是傳入的值是undefined,則返回"undefined";

var value1 = 10;
var value2 = true;
var value3 = null;
var value4;

alert(String(value1)); // "10"
alert(String(value2)); // "true"
alert(String(value3)); // "null"
alert(String(value4)); // "undefined"

ES數據類型之 Object 類型

ES中的Object(對象)就是一組數據和功能的集合。
Object類型是全部其餘類型的基礎,因此Object類型的因此屬性和方法也會存在於其餘具體的對象中。

var o1 = new Object(); //建立一個自定義對象

Object實例擁有的屬性和方法

屬性/方法 解析
constructor 保存着用於建立對象的函數。對於前面的例子而言,構造函數(constructor)就是Object()。
hasOwnProperty(propertyName) 用於檢查給定的屬性(propertyName)在當前的對象實例中(而不是在實例的原型中)是否存在。propertyName必須以字符串形式指定。
isPrototypeOf(object) 用於檢查傳入的對象是不是傳入對象的原型。(?)
propertyIsEnumerable(propertyName) 檢查給定的屬性(propertyName)是否能用for-in語句枚舉。propertyName必須以字符串形式指定。
toLocaleString() 返回對象的字符串表示,該字符串與執行環境的地區對應。
toString() 返回對象的字符串表示。
valueOf() 返回對象的字符串、數值或布爾值表示。一般與toString()方法的返回值相同。

操做符

包括 一元操做符位操做符布爾操做符乘性操做符加性操做符關係操做符相等操做符條件操做符賦值操做符逗號操做符

一元操做符

遞增與遞減操做符(包括前置型與後置型)
//前置型操做符
var n1 = 25;
++n1;
 
var n2 = 25;
--n2;

//前置型操做符會在求值前被執行
var age = 25;
var anotherAge = --age + 2;

console.log(age); //24 (在下一句執行以前已經執行了自減)
console.log(anotherAge); //26 (24+2)
//後置型操做符
var n1 = 25;
n1++;

//後置型操做符會在被求值以後才執行,注意如下問題
var n1 = 2;
var n2 = 20;
var n3 = n1-- + n2; 
console.log(n3); //計算n3時使用了原始值計算,因此輸出22
var n4 = n1 + n2; 
console.log(n4); //計算n4時,n1已經被遞減,因此輸出21

上述的4個操做符能夠用於整數浮點數字符串布爾值對象運算;

var s1 = "2"; 
console.log(++s1);//轉換爲數值2再參與運算,輸出3
var s2 = "a"; 
console.log(++s2);//值爲NaN,沒法參與運算
var s3 = false; 
console.log(++s3);//轉換爲數值0再參與運算,輸出1, **true則轉換爲1**
var s4 = 2.1; 
console.log(--s4); //參與減一運算,注意浮點數舍入錯誤問題,輸出1.1
console.log(++s4); //參與加一運算,注意浮點數舍入錯誤問題,輸出2.1
var s5 = {
  valueOf: function(){
    return -1;
  }
};
console.log(++s5); //先調用對象的valueOf()方法,取得一個可供操做的值,而後把該值應用於前述規則;若是結果是NaN,則調用toString()方法後再應用前述規則。對象變量變成數值變量,這裏輸出0
console.log(++s5); //輸出1

一元加和減操做符

+-
對非數值應用一元加和減操做符時,會像Number()轉型函數同樣對這個值執行轉換

/*一元加操做符*/
var s1 = "01";
var s2 = "1.1";
var s3 = "z";
var b = false;
var f = 1.1;
var o = {
    valueOf: function() {
        return -1;
    } 
};
s1 = +s1; //1
s2 = +s2; //1.1
s3 = +s3; //NaN
b= +b; //0
f= +f; //1.1
o= +o; //-1

/*一元減操做符*/
//一元減操做符主要用來表示負數
var n1 = 1;
n2 = -n1; //-1

位操做符 (略)


布爾操做符

非(NOT),與(AND),或(OR)

邏輯非!

返回一個布爾值, 而後再對其求反

alert(!false); //true
alert(!"blue"); //false
alert(!0); //true
alert(!NaN); //true
alert(!""); //true
alert(!12345); //false
alert(!undefined); //true
alert(!null); //true
var i = function(){};
alert(!i); //false
邏輯與&&

有兩個操做數, 只有兩個操做數都返回true時, 才返回true; 不然返回false

var i = function(){};
var j = function(){console.log("funciton j")};
alert(i && true); //true
alert(i && false); //false

alert(true && i); //function(){}
alert(false && i); //false
alert(i && j); //function(){console.log("funciton j")};
//若是有一個操做數是null, NaN或undefined, 則返回該三者之一
alert(null && false); //null
alert(null && true); //null
alert(null && i); //null
/*邏輯與屬於短路操做, 即若是第一個操做數能決定結果,就不會再對第二個操做數求值*/
var f = true;
var r = (f && cc); //cc未聲明 
alert(r); //這一句不會執行,由於上面的cc未聲明. Uncaught ReferenceError: cc is not defined(…)

//若是f爲false,則會執行並返回false, 由於第一個操做數已是false, 因此就不會再對後面的操做數求值了
var f = false;
var r = (f && cc); //cc未聲明
alert(r); //false
邏輯或||

有兩個操做數, 只要有一個操做數都返回true, 就會返回true;

var i = function(){};
var j = function(){console.log("funciton j")};
alert(i || true); //function(){};
alert(i || false); //function(){};
alert(i || j); //function(){};
alert(true || i); //true
alert(false || i); //function(){};
alert(null || false); //false
alert(null || true); //true
alert(null || i); //function(){};
//若是兩個操做數都是null, NaN, undefined, 則會返回一樣的結果.
//邏輯或也屬於短路操做
var f = true;
var r = (f || cc); //cc未聲明 
alert(r); //會執行true

var f = false;
var r = (f || cc); //cc未聲明
alert(r); //這一句不會執行,由於上面的cc未聲明. Uncaught ReferenceError: cc is not defined(…)
/*正常開發中, 可使用邏輯與來避免爲變量賦null或undefined值*/
var o = preferredObject || backupObject;
//backupObject提供一個後備值, 若是preferredObject不包含指望的有效值的狀況下, backupObject會被賦值給o, 不然在常常狀況下, preferredObject賦值給o.

乘性操做符

*, 乘法,用於計算兩個值的乘積

alert(2 * 2); //4
alert(2 * -2); //-4
alert(NaN * 2); //NaN
alert(Infinity * 0); //NaN
alert(Infinity * 1); //Infinity
alert(Infinity * -1); //-Infinity
alert(Infinity * Infinity); //Infinity
//在操做數不是數值的狀況下, 後臺會調用Number()將其轉換爲數值,而後在進行運算

/, 除法,第二個操做數除第一個操做數

alert(2 / 2); //1
alert(2 / -2); //-1
alert(2 / NaN); //NaN
alert(Infinity / Infinity); //NaN
alert(0 / Infinity); //0
alert(Infinity / 0); //Infinity
alert(0 / 0); //NaN
alert(0 / 2); //0
alert(2 / 0); //Infinity
alert(-2 / 0); //-Infinity
//在操做數不是數值的狀況下, 後臺會調用Number()將其轉換爲數值,而後在進行運算

加性操做符

+, 加法

alert(1 + 2); //3
alert(NaN + 1);//NaN
alert(Infinity + Infinity); //Infinity
alert(-Infinity + (-Infinity)); //-Infinity
alert(Infinity + (-Infinity)); //NaN
alert(0 + 0); //0
alert(-0 + (-0)); //0
alert(0 + (-0)); //0
alert(1+'2'); //12, 字符串拼接
//注意加法操做中的數據類型錯誤
var num1 = 5;
var num2 = 10;
var message = "The sum of 5 and 10 is " + num1 + num2;
alert(message);    // 獲得的結果是 : "The sum of 5 and 10 is 510"

//應該像下面這樣使用括號
var num1 = 5;
var num2 = 10;
var message = "The sum of 5 and 10 is " + (num1 + num2); 
alert(message); //"The sum of 5 and 10 is 15"

-, 減法

alert(2 - 1);
alert(NaN - 1); //NaN
alert(Infinity - Infinity); //NaN
alert(-Infinity -(-Infinity)); //NaN
alert(Infinity -(-Infinity)); //Infinity
alert(-Infinity - Infinity); //-Infinity
alert(0 - 0); //0
alert(0 - (-0)); //-0
alert(-0 -(-0)); //0
alert(5 - true); //4, ture to 1
alert(5 - ""); //5, "" to 0
alert(5 - "2"); //3, "2" to 2
alert(5 - null); //5, null to 0

關係操做符

小於<, 大於>, 小於等於<=, 大於等於>=, 均返回一個布爾值

var r = 5 > 4; //true
var r = 5 < 4; //false
//在字符串的比較中, 決定結果的是字符串字母(大小寫)的字符編碼, 而不是字母的順序 : 
alert("app" > "back"); //false
alert("app" > "Back"); //true
alert("App" > "Back"); //false
//因字符編碼的順序不一樣, 因此在進行比較時應該把字符串統一轉換成大寫或者小寫再進行比較;
alert("App".toLowerCase() > "Back".toLowerCase()); //false

//一樣的, 數字字符串也會比較的是字符編碼 : 
alert("15" > "4"); //false
//把其中一個變成數值類型, 或者使用有效的轉型函數轉型成數值, 結果就正常了 :
alert("15" > 4); //true
alert(Number("15") > Number("4")); //true

//NaN跟任何數值比較均返回false
alert(NaN > 4); //false
alert(NaN < 4); //false

相等操做符

相等==和不相等!=, 全等===和不全等!==
相等和不相等在比較前都會先轉換操做數, 而後再進行比較

相等和不相等
//布爾值會被先轉換成0和1
alert(1 == true); //true
alert(2 == true); //false
alert(0 == false); //true
alert("a" == 1); //false
var a = "jon";
var b = "percy";
var c = a;
alert(a == c); //true, 比較兩個對象時, 若是兩個對象指向的是同一個對象,則返回true, 不然返回false
alert(a == b); //false
alert(a == 1); //false
alert(null == undefined); //true
alert(undefined == 0); //false
alert(null == 0); //false
alert(5 == "5"); //true
alert("NaN" == NaN); //false
alert(5 == NaN); //false
alert(NaN == NaN); //false, NaN不等於自身
全等和不全等

全等和不全等不會像上面的相等和不相等同樣進行數據類型轉換, 而是直接進行比較 :

alert(55 == "55"); //相等比較下, 會進行數據轉換, 因此返回true
alert(55 === "55"); //全等比較下, 不會進行數據轉換, 因此這裏返回false
/*注意null和undefined進行全等比較會返回false, 由於他們是相似的值(因此相等比較會返回true)可是屬於不一樣類型的值*/
alert(null == undefined); //false

條件操做符(三目運算符)

//對boolean_expression求值, 若是結果爲true則返回true_value(給variable), 不然返回false_value(給variable)
variable = boolean_expression ? true_value : false_value;
var num1 = 4;
var num2 = 6;
var max = (num1 > num2) ? num1 : num2;
console.log(max); //6

賦值操做符

  • 簡單的賦值操做符=

  • 乘/賦值*=

  • 除/賦值/=

  • 模/賦值%=

  • 加/賦值+=

  • 減/賦值-=

  • 左移/賦值<<=

  • 有符號右移/賦值>>=

  • 無符號右移/賦值>>>=

var n = 2;
n = n + 2; //4 

//能夠簡化成
n += 2;

//其餘原理相同

逗號操做符

//可用於同時聲明多個變量
var a, b, c;

語句

ES指流程控制語句

if語句

if(condition){
    statement1
}else{
      statement2
}
var i = 20;
if(i > 25){
  console.log("i is greater than 25");
}else{
  console.log("i is less than or equal to 25");
}
//i is less than or equal to 25
if(condition1){
  statement1
}else if(condition2){
  statement2
}else{
  statement3
}
var i = 25;
if(i > 25){
  console.log("i is greater than 25");
}else if(i == 25){
  console.log("i is equal to 25");
}else{
  console.log("i is less than 25");
}
//i is equal to 25

do-while語句

do-while語句在對錶達式求值以前, 循環體內的代碼會被最少執行一次

do{
  statement
}while(expression)
var i = 2;
do{
  i += 2;
  console.log(i);
}while(i < 7);
//之因此出現8的緣由是, 當i遞增到6的時候依然少於7, 因此在判斷while裏面的條件以前依然會被遞增一次
//4, 6, 8
var i = 10;
do{
  i ++;
  console.log(i);
}while(i < 10);
//雖然while裏面的條件已經不知足,但do裏面的語句仍是會被執行一次, 輸出11

while語句

與do-while語句相反, while語句會在循環體(expression)內的代碼被執行以前, 先對條件求值

while(expression){
  statement
}
var i = 10;
while(i < 20){
  i+=2;
  console.log(i);
  //12, 14, 16, 18, 20
}
console.log("the last i is : " + i); //20

for語句

for與while同樣, 也是前測試循環語句, 但它能夠在執行循環以前初始化變量定義循環後要執行的代碼

for(initialization; expression; post-loop-expression){
  statement;
}
var c = 10;
for(var i = 1; i <= c; i+=2){
  console.log(i);
}
//1, 3, 5, 7, 9
//提早定義好變量, 就能夠在for語句裏面省略var關鍵字
var i, c = 10;
for(i = 1; i <= 10; i+=3){
  console.log(i);
  //1, 4, 7, 10
}
//注意ES裏面沒有塊級做用域, 因此下面的語句能夠正常輸出
console.log("the last i is : " : i); //10

for-in語句

for-in是精準的迭代語句, 能夠用來枚舉對象的屬性

for(property in expression){
  statement
}
var arr = ['Jon','Martin','Percy'];
for(var i in arr){
  console.log(arr[i]);
  //Jon, Martin, Percy
}
//注意for-in語句輸出的結果順序是不可預測的
//做爲最佳實踐, 使用for-in語句時, 應該確認該對象的值不是null或undefined

label語句

label語句能夠在代碼中添加標籤, 以便在未來被break或continue引用

label : statement
first : for(var i = 0; i < 10; i+=2){
  console.log(i);
}
//first做爲for循環的標籤

break與continue語句

break與continue語句用於在循環中精確的控制代碼的執行;

break會當即退出循環, 強制執行後面的語句

continue也會當即退出循環, 但退出後會從循環的頂部繼續執行

//break
var n = 0; //初始化計算累積次數的變量
for(var i = 1; i < 10; i++){ //i從1遞增到10
  if(i % 5 == 0){ //遞增過程當中判斷i是否能被0整除
      break; //是的話當即退出循環,這裏在i=5的時候退出了循環
  }
  n++; //每循環一次累積計算次數
}
console.log(n); //退出循環以前,循環體執行了4次,因此輸出4
//continue
var n = 0; //初始化計算累積次數的變量
for(var i = 1; i < 10; i++){ //i從1遞增到10
  if(i % 5 == 0){ //遞增過程當中判斷i是否能被0整除
      continue; //是的話當即退出循環,這裏在i=5的時候退出了循環, 而且回到循環頂部繼續執行(在for循環條件未知足以前繼續執行)
  }
  n++; //每循環一次累積計算次數
}
console.log(n); //退出循環以前(for循環結束以前),循環體執行了8次(由於在5被整除的時候退出了循環,致使循環體少執行了一次),因此最終輸出8

與label標籤配合使用

//break
var i, j, n = 0;
outerloop:
for(i = 0; i < 10; i++){
  for(j = 0; j < 10; j++){
    if(i == 5 && j ==5){
        break outerloop;
    }
    n++;
  }
}
//正常來講, i每遞增1次, j就會遞增10次, 因此n最終值在不受干擾的狀況下回等於100
//這裏判斷若是i和j都等於5的狀況下回當即退出循環, 因此循環體最終會退出內部和外部的for循環(退回標籤outerloop的位置), 因此最終n會輸出55
console.log(n); //55
//continue
var i, j, n = 0;
outerloop:
for(i = 0; i < 10; i++){
  for(j = 0; j < 10; j++){
    if(i == 5 && j ==5){
        continue outerloop;
    }
    n++;
  }
}
//這裏判斷若是i和j都等於5的狀況下回當即退出循環, 但退回外部的for循環(outerloop標籤)的循環以後會繼續強制執行外部循環, 因此最終會獲得95
console.log(n); //95

with語句

with語句做用是將代碼的做用域設置到一個特定的對象中

with(expression){
  statement;
}
//定義with語句的目的主要是簡化屢次編寫同一個對象的工做
var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href;

//使用with語句上面的代碼能夠改爲
with(location){
  var qs = search.substring(1);
  var hostName = hostname;
  var url = href;
}
//嚴格模式下不容許使用with, 不然會報錯
//with會致使性能降低, 在大型項目中不建議使用

switch語句

switch(expression){
  //若是expression等於value, 則執行後面的statement, 並跳出當前循環
  case value : statement
  break;
  case value : statement
  break;
  case value : statement
  break;
  case value : statement
  break;
  //若是expression不等於前面任何一個value, 則使用default內的statement代碼
  default : statement
}

var i = 2;
switch(i){
    case 1 : 
    console.log("result is 1");
    break;
    
    case 2;
    console.log("result is 2");
    break;
    
    default : 
    console.log("what is the result?");
}

//能夠合併兩種情形(cast)
switch(i){
  case 1 :
  case 2 :
  console.log("1 or 2");
  break;
  
  case N...
}

函數

函數能夠封裝任意多條語句, 且能夠在不一樣地方, 不一樣時間調用執行.

使用關鍵字function聲明,後面跟一組參數以及函數體

function functionName(arg0, arg1, arg2, ...argN){
  statements;
}

//實例
function sayHi(name, age){
  console.log("my name is " + name +", age is" + age + ".");
}
//調用
sayHi("Jon",25);
//輸出my name is Jon, age is 25.
//使用return語句後面跟要返回的值來實現返回值
function sum(n1, n2){
  return n1 + n2;
}
var r = sum(1 + 2);
alert(r); //3
//注意在return後面的語句永遠不會執行
function sum(n1, n2){
  return n1 + n2;
  console.log("Hi!"); //永遠不會執行
}
//一個函數中能夠包含多個return語句
function diff(n1 ,n2){
  if(n1 < n2){
      return n2 - n1;
  }else{
    return n1 - n2;
  }
}

//return能夠不帶有任何返回值,通常用在須要提早執行函數執行有不須要返回值的狀況下.
function sayHi(name, message){
  return;
  console.log("Hi! " + name + "," + message); //永遠不會調用
}
//推薦的作法是要麼讓函數始終返回一個值, 要麼永遠不會返回值

理解參數

  • ES中的參數不限定數量和數據類型

  • 假設被調用的函數的參數定義了兩個, 在調用這個函數時也不強制須要傳入兩個, 能夠少傳或多穿而不會報錯, 命名的參數只是爲了便利, 並非必須的

  • ES函數的參數內部是一組類數組, 在函數體內能夠經過arguments對象來訪問這組數組的內容, 訪問的時候像訪問數組同樣, 使用方括號語法arguments[0], arguments[1], arguments[2], arguments[n] ...

    //上面的sum函數例子能夠寫成
    function sum(n1, n2){
      //return n1 + n2;
      return arguments[0] + arguments[1];
    }
    sum(1 , 2); //3
//訪問arguments的length屬性能夠知道多少個參數傳遞給了函數
function howManyArgs(){
  console.log(arguments.length);
}
howManyArgs(); //0
howManyArgs(1); //1
howManyArgs(1,2); //2

//能夠利用這一點讓函數在接收不一樣參數時執行不一樣的功能
function doAdd(n1, n2){
  if(arguments.length == 1){
    console.log(arguments[0] + 2);
  }else if(arguments.length == 2){
      console.log(arguments[0] + arguments[1]);
    //argument對象能夠和命名參數混合使用
    //console.log(arguments[0] + n2); //沒有問題!
  }
}
doAdd(1); //3
doAdd(2,3); //5
  • arguments的值和對應的命名參數的值會保持同步

    function doAdd(n1, n2){
      arguments[1] = 10;//注意嚴格模式下會無效,n2仍然等於undefined
      console.log(arguments[0] + n2); 
    }
    doAdd(12,1); //22, 而不是13
    //嚴格模式下重寫arguments的值會致使語法錯誤, 代碼不能執行
  • ES中全部參數傳遞都是值, 不可能經過引用傳遞參數

沒有重載

其餘語言中能夠爲一個函數編寫兩個定義, 只要這兩個定義的簽名(接受的參數類型和數量)不一樣便可

ES中的參數是由包含零個或多個值的數組來表示的, 而沒有函數簽名, 真正的重載是不可能的

若是定義了兩個名字相同的函數, 那麼更名字只屬於後定義的函數

function add(n){
  return n + 10;
}
function add(n){
  return n + 20;
}
add(1); //21

經過檢查傳入函數中參數的類型和數量並做出不一樣的反應, 能夠模擬方法的重載.

相關文章
相關標籤/搜索