JavaScript學習筆記 - 基本概念

本文記錄了我在學習前端上的筆記,方便之後的複習和鞏固。javascript

3.1.4 嚴格模式

嚴格模式是JavaScript定義了一種不一樣的解析和執行模型。在嚴格模式下ECMAScript3中的一些不肯定行爲將獲得處理,並且對某些不安全的操做也會拋出錯誤。要在整個腳本中啓用嚴格模式,能夠在頂部添加以下代碼:前端

"use strict";

這段代碼看起來像字符串,並且也沒賦值給任務變量,但其實它是一個編譯指示(pragma),用於告訴支持的JavaScript引擎切換到嚴格模式。這是爲不破壞ECMAScript3而特地選定的語法。
在函數內部的上方包含這條編譯提示,也能夠指定函數在嚴格模式下執行:java

function doSomething() {
    "use strict";
    //函數體
}

3.2 關鍵字和保留字

ECMAScript5關鍵字:
break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with
ECMAScript5非嚴格模式保留字:
class、enum、extends、super、const、export、import
在嚴格模式下,第5版還對一下保留字施加了限制:
implements、package、public、interface、private、static、let、protected、yieldexpress

3.3 變量

局部變量被函數調用後,當前函數退出後就會被銷燬,例如:數組

function test(){
    var message = "hi"; //局部變量
}
test();
alert(message); //錯誤

全局變量就不會:安全

function test(){
    message = "hi"; //全局變量
}
test();
alert(message); // "hi"

這樣,只要調用過一次test()函數,這個變量就有了定義,就能夠在函數外部任何地方被訪問到。但全局變量的作法不推薦。由於在局部做用域中定義的全局變量很難維護。
嚴格模式下不能定義名爲evalarguments的變量,不然會致使語法錯誤。函數

3.4 數據類型

ECMAScript中有五種簡單數據類型:性能

  • Undefined學習

  • Null測試

  • Boolean

  • Number

  • String

還有一種複雜數據類型——Object

注意:ECMAScript6還新增了一種數據類型符號對象 - (Symbol) - 符號對象簡介

3.4.1 typeof操做符

用於檢測給定變量的數據類型——typeof就是負責提供這方面信息的操做符。對一個值使用typeof操做符可能返回下列某個字符串:

  • "undefind"——若是這個值未定義;

  • "boolean"——若是這個值是布爾值;

  • "string"——若是這個值是字符串;

  • "number」——若是這個值是數值;

  • "object" ——若是這個值是對象或null;

  • "function"——若是這個值是函數
    下面是幾個使用typeof操做符的例子:

var message = "some string";
alert(typeof message); //"string"
alert(typeof (message)); //"string"
alert(typeof 95); //"number"

注意:調用typeof null 會返回 "object",由於特殊值null被認爲是一個空的對象引用。

3.4.2 Undefind類型

Undefined類型只有一個值即undefind。在使用var聲明變量後但未對其加以初始化時,這個變量的值就是undefined,例如:

var message;
alert(message == undefined); //true
var message1 == undefined
alert(message1 == undefined); //true

typeof操做符對未初始化和未聲明的變量都返回undefined

3.4.3 Null類型

Null類型是第二個只有一個值的數據類型,這個特殊的值是null。從邏輯角度看,null值表示一個空對象指針,而這也正是使用typeof操做符檢測null值會返回"object"的緣由

var car = null;
console.log(typeof car); //"object"

若是定義的變量是爲了之後要保存對象,那麼最好該變量初始化爲null值。

if(car != null){
    //對car對象執行某些操做
}

undefined值是派生自null的值得因此:

console.log(null == undefined); //true

3.4.4 Boolean類型

該類型只有兩個字面值: truefalse
雖然Boolean類型只有兩個字面值,可是能夠調用Boolean()函數把值轉換爲對應的Boolean值:

var message = "Hello World!";
var messageAsBoolean = Boolean(message);

轉換規程:

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

3.4.5 Number類型

//十進制
var intNum = 55; //整數
//八進制
var octalNum1 = 070;//八進制56
var octalNum1 = 079;//無效的八進制數值——解析爲79
var octalNum1 = 08;//無效的八進制數組——解析爲8
//十六進制
var hexNum1 = 0xA; //十六進制的10
var hexNum2 = 0x1f;    //十六進制的31

八進制:第一位必須是零(0),而後是八進制數字序列(0~7).若是字面值中的數值超出了範圍,那麼前導零將被忽略,後面的數值當成十進制解析。
十六進制:前兩位必須是0x,後跟任何十六進制數字(0~9,A~F)。

注意:在算數計算時,全部的八進制和十六進制表示的數值最終都將被轉換成十進制。

1.浮點數值

浮點數值中必須包含個小數點

var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1    //有效但不推薦

因爲保存浮點數值須要的空間是整數數值的兩倍,所以ECMAScript會不失時機的將浮點數值轉換成整數值。

var floatNum1 = 1.;  //小數點後面沒有數字——解析爲1
var floatNum2 = 10.0 //整數——解析爲10

對於極大或極小的數值,能夠用e表示法。

var floatNum  = 3.125e7; //31250000

浮點數值最高精度是17位小數,但在進行算數計算時它的精度遠遠不如整數。例如0.1加0.2不是0.3 ,而是0.30000000000000004。這個小小的舍入偏差會致使沒法測試特定的浮點數值。例如:

if(a + b == 0.3){        //不要這樣作測試
    alert("You got 0.3");
}

在這個例子中若是兩個數是0.05和0.25或者是0.15和0.15都不會有問題。所以永遠不要測試某個特定的浮點數值。

3.NaN

NaN,既非數值,是這個特殊的數值,這個數值用於表示一個原本要返回的數值的操做數未返回數值的狀況(這樣就不會拋出錯誤了)。
NaN自己有兩個非同尋常的特色。首先,任何涉及NaN的操做(例如NaN/10)都會返回NaN。其次NaN與任何值都不想等,包括NaN自己。例如:

console.log(NaN == NaN); //false

針對NaN這兩個特色,ECMAScript定義了isNaN()函數。這個函數接受一個參數,該參數能夠是任何類型,2️⃣函數會幫咱們肯定這個參數是否"不是數值"。
isNaN()接受到第一值後,會嘗試將這個值轉換爲數值。任何不能被轉換的數值的值都會致使這個函數返回true。例如:

console.log(isNaN(NaN));  //true
console.log(isNaN(10));  //false(10是一個數值)
console.log(isNaN("10"));  //false(能夠被轉換成數值10)
console.log(isNaN("blue"));  //true(不能轉換成數值)
console.log(isNaN(true));  //flase(能夠被轉換成數值1)

isNaN也適用於對象,在基於對象調用isNaN()函數時,會首先調用valueOf()方法,而後肯定該方法返回的值是否能夠轉換爲數值。若是不能,則基於這個返回值再調用toString()方法,再測試返回值

4.數值轉換

有3分函數能夠把非數值轉換爲數值:

  • Number()——可用於任何數據類型

  • parseInt()——專門用於把字符串轉換成整數數值

  • parseFloat()——專門用於把字符串轉換成浮點數值

Number()函數的轉換規則以下

  • 若是是Boolean值,truefalse將分別被轉換爲1和0.

  • 若是是數字值,只是簡單的傳入和返回

  • 若是是null值,返回0

  • 若是是undefined,返回NaN

var num1 = Number("Hello world!");  //NaN
var num2 = Number("");              //0
var num3 = Number("000011");        //11
var num4 = Number("true");          //1

parseInt()
因爲Number()在轉換字符串時比較複雜並且不夠合理,所以在處理整數的時候更經常使用的事parseInt()函數。

var num1 = parseInt("1234bule"); //1234
    var num2 = parseInt("");         //NaN
    var num3 = parseInt("0xA");      //10(十六進制數)
    var num4 = parseInt("22.5");     //22
    var num5 = parseInt("070");      //56(八進制數)
    var num6 = parseInt("70");       //70(十進制數)
    var num7 = parseInt("0xf");      //15(十六進制數)
    
    //在ES3和ES5存在分歧。例如:
    var num = parseInt("070");       //ES3認爲是56(八進制)  ES5認爲是70(十進制)
    
    //parseInt()函數有第二個參數:轉換時使用的基數(進制)
    var num = parseInt("0xAF", 16)   //175(按十六進制解析)
    //使用了16進制參數,字符串能夠不帶0x
    var num1 = parseInt("AF", 16)    //175
    var num1 = parseInt("AF")        //NaN

不知道基數意味着讓parseInt()決定如何解析字符串,所以爲了不錯誤的解析,建議不管在什麼狀況都明確指定基數。

parseFloat()

var num1 = parseFloat("123bule");      //1234(整數)
var num2 = parseFloat("0xA");          //0
var num3 = parseFloat("22.5");         //22.5
var num4 = parseFloat("22.34.5");      //22.34
var num5 = parseFloat("0908.5");       //908.5
var num6 = parseFloat("3.125e7");      //31250000

3.4.6 String類型

1.字符字面量

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

2.字符串的特色

ECMAScript中的字符串是不可變的,也就是說,字符串一旦建立,它們的值就不能改變。要改變某個變量保存的字符串,首先要銷燬原來的字符串,而後在用另外一個包含新值得字符串填充該變量例如:

var lang = "Java";
lang = lang + "Script"; //JavaScript

3.轉換爲字符串

toString()方法

var age = 11;
var ageAsString = age.toString; //字符串"11";
var found = true;
var foundAsString = found.toString; //字符串"true";

數值、布爾值、對象、字符串值都有toString()方法。但nullundefined值沒有這個方法。
toString()方法也跟上面的parseInt()方法相似同樣有一個參數:輸出數值的基數;

var num = 10;
console.log(num.toString());    //"10"
console.log(num.toString(2));    //"1010"
console.log(num.toString(8));    //"12"
console.log(num.toString(10));  //"10"
console.log(num.toString(16));  //"a"

在不知道要轉換的值是否是null或undefined的狀況下,還可使用轉型函數String(),這個函數可以將任何類型的值轉換成字符串。String()函數遵循下列轉換規則:

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

  • 若是值是null,則返回"null";

  • 若是值是undefined,則返回"undefined"。

下面看幾個例子:

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

console.log(String(value1));  //"10"
console.log(String(value2));  //"true"
console.log(String(value3));  //"null"
console.log(String(value4));  //"undefined"

3.4.7 Object類型

ECMAScript中的對象其實就是一組數據和功能的集合。對象能夠經過執行new操做符後跟要建立的對象類型的名稱來建立。而建立Object類型的實例併爲其添加屬性和方法,就能夠建立自定義對象,以下所示:

var o = new Object();

若是不給構造函數傳遞參數,則能夠省略後面的括號,可是這作法不推薦

var o = new Object;  //有效,但不推薦省略圓括號

僅僅建立Object的實例並無什麼用處,但關鍵是要理解一個重要的思想:即在ECMAScript中,Object類型是全部它的實例的基礎。換句話說,Object類型所具備的任何屬性和方法也一樣存在於更具體的對象中。
Object的每一個實例都具備下列屬性和方法:

  • constructor:保存着用於建立當前對象的函數。對於前面的例子而已,構造函數(constructor)就是Object();返回一個指向建立了該對象原型的函數引用。該屬性的值就是那個函數自己

  • hasOwnProperty(propertyName):用於檢查給定的屬性在當前對象實例中(而不是在實例的原型中)是否存在,其中,做爲參數的屬性名(propertyName)必須以字符串的形式指定例如:o.hasOwnProperty("name");

  • isPrototypeOf(Object):用於檢查傳入的對象是不是當前對象的原型

  • propertyIsEnumerable(propertyName):用於檢查給定的屬性是否可以使用for-in語句來枚舉。與hasOwnProperty()方法同樣,做爲參數的屬性名必須以字符串形式指定。

  • toLocaleString():返回對象的字符串表示,該字符串與執行環境的地區對應。

  • toString():返回對象的字符串表示。

  • valueOf():返回對象的字符串、數值、或布爾值表示。一般與toString()方法的返回值相同。
    因爲在ECMAScriptObject是全部對象的基礎,所以全部對象都具備這些基本的屬性和方法。

3.5 操做符

ECMA-262描述了一組用於操做數據值的操做符,包括算數操做符(如加號和減號)、位操做符、關係操做符和相等操做符。ECMAScript操做符的不同凡響之處在於,它們可以使用於不少值,例如字符串、數字值、布爾值、甚至對象。不過在應用於對象時,相應的操做符一般都會調用對象的valueOf()和(或)toString()方法,以便取得能夠操做的值。

3.5.1 一元操做符

1.遞增和遞減操做符
執行前置遞增和遞減操做時,變量的值都是在語句被求值之前改變的。

var age = 29;
var anotherAge = --age + 2;

console.log(age); //28
console.log(anotherAge);  //30

因爲前置遞增和遞減操做與執行語句的優先級相等,所以整個語句會從左至右被求值。

var num1 = 2;
var num2 = 20;
var num3 = --num1 + num2;//21
var num4 = num1 + num2;  //21

num4相應的加法操做使用了num減去1以後的值

後置遞增和遞減操做符語法不變,他們的區別就是前置遞增和遞減被操做時變量的值都是在語句被求值之前改變的。然後置是求值以後才執行的。

把遞增操做符放在後面並不會改變語句的結果。

var num1 = 2;
var num2 = 20;
var num3 = num1-- + num2;//22
var num4 = num1 + num2;  //21

遞增和遞減操做符對任何值都使用,字符串,布爾值,浮點數值,對象

3.5.3 布爾操做符

1.邏輯非
邏輯非操做符由一個歎號( ! )表示,能夠應用於ECMAScript中的任何值。不管這個值是什麼數據類型,這個操做符都會返回一個布爾值。邏輯非操做符首先會將她的操做數轉換爲一個布爾值,而後再對其求反。

邏輯非操做符也能夠用於將一個值轉換爲與其對應的布爾值。而同時使用兩個邏輯非操做符。實際上就會模擬Boolean()轉型函數的行爲。其中,第一個邏輯非操做會基於不管什麼操做數返回一個布爾值,而第二邏輯非操做則對該布爾值求反,因而就獲得了這個值正對應的布爾值。固然,最終的結果與對這個值使用Boolean()相同

2.邏輯與
邏輯與操做符由兩個和號(&&)表示,有兩個操做數,以下面的例子所示:

var result = true && false;

邏輯與操做能夠應用於任何類型的操做數,而不只僅是布爾值。在有一個操做數不是布爾值的狀況下,邏輯與操做就不必定返回布爾值;此時它遵循下列規則:

  • 若是第一個操做數是對象,則會返回第二個操做數;

  • 若是第二個操做數是對象,則只有在第一個操做數的求值結果爲true的狀況下才會返回該對象;

  • 若是兩個操做數都是對象,則返回第二個操做數;

  • 若是有一個操做數是null,則返回null

  • 若是有一個操做數是NaN,則返回NaN

  • 若是有一個操做數是undefined,則返回undefined

邏輯與操做屬於短路操做,即若是第一個操做數可以決定結果,那麼就不會再對第二個操做數求值。對於邏輯與而言,若是第一個操做數是false,則不管第二個操做數是什麼值,結果都再也不多是true了。例子:

var found = true;
var result = (found && someUndefinedVariable) //這裏會發生錯誤
alert(result)  這一行不會執行

上面例子發生錯誤,由於變量someUndefinedVariable沒有聲明。因爲變量found的值是true,因此邏輯與操做符會繼續對變量someUndefinedVariable求值。因此邏輯與操做符會繼續對變量someUndefinedVariable求值。但someUndefinedVariable沒定義因此就致使錯誤。將found的值設置爲false,就不會發生錯誤了。

3.邏輯或
邏輯或操做符由兩個和號(||)表示,有兩個操做數,以下面的例子所示:

var result = true || false;

與邏輯與操做類似,若是有一個操做數不是布爾值,邏輯或也不必定返回布爾值;此時它遵循下列規則:

  • 若是第一個操做數是對象,則會返回第一個操做數;

  • 若是第一個操做數的求值結果爲false,則返回第二個操做數。

  • 若是兩個操做數都是對象,則返回第一個操做數;

  • 若是有兩個操做數是null,則返回null

  • 若是有兩個操做數是NaN,則返回NaN

  • 若是有兩個操做數是undefined,則返回undefined
    與邏輯與操做符類似,邏輯或操做符也是短路操做符。若是第一個操做數的求值結果爲true,就不會對第二個操做值求值了,跟邏輯與是相反的。

3.5.6

小於(<)、大於(>)、小於等於(<=)和大於等於(>=)

ECMAScript中的其餘操做符同樣,當關系操做符的操做數使用了非數值時,也要進行數據轉換或完成某些奇怪的操做。一下就是相應的規則。

  • 若是兩個操做符都是數值,則執行數值比較;

  • 若是兩個操做數都是字符串,則比較兩個字符串對應的字符編碼值;

  • 若是一個操做數是數值,則另外一個操做數轉換爲一個數值,而後執行數值比較;

  • 若是一個操做數是對象,則調用這個對象的valueOf()方法,並用獲得的結果根據前面的規則執行比較。若是對象沒有valueOf()方法,則調用toString()方法,並用獲得的結果根據前面的規則執行比較;

  • 若是一個操做數是布爾值,則將他轉換爲數值,而後執行比較。

任何數與NaN比較都返回false

3.5.7 相等操做符

1.相等和不相等

== 兩個數相等 返回true
!= 兩個數不相等 返回ture
要比較相等性以前,不能將null和undefined轉換成其餘任何值。
若是兩個操做數都是對象,則比較它們是否是同一個對象,若是兩個操做數都指向同一個對象則true,不是則false;

注意:nullundefined是相等的,NaN不等於NaN

2.全等和不全等
全等和相等相似,二者最大區別是全等比較時不轉換成數值。
全等和不全等的比較都是在操做數未經轉換的狀況下比較。

注意:null == undefined返回true,由於他們相似的值;但null === undefined返回false,由於他們是不一樣類型的值

3.5.8 條件操做符

variable = boolean_expression ? true_value : false_value;
var max = (num1 > num2) ? num1 : num2;

3.6語句

3.6.1 if語句

if(condition) statement1 else statement2
if(i > 25) {
    alert("Greater than 25.");    
}else{
    alert("Less than of equal to 25.");
}

3.6.2 do-while

var i = 0;
do {
    i+=2;
}while(i < 10);
console.log(i);

3.6.3 while

var i = 0;
while(i < 10) {
    i += 2;
}

3.6.4 for 語句

var count = 10;
for(var i = 10; i < count; i++){
    console.log(i);
}

因爲ECMAScript中不存在塊級做用於,所以在循環內部定義的變量也能夠在外部訪問到。

注意:for語句中的初始化表達式、控制表達式和循環後表達式都是可選的。將這三個表達式所有省略,就會建立一個無限循環。

3.6.5 for-in語句

var data = [1,3,2,4,5];
for(var propName in data){
    console.log(data[propName]); //1,3,2,4,5
    console.log(propName); //0,1,2,3,4
}
for(var propName in window){
    console.log(propName); //window對象屬性名
}

注意:ECMAScript對象屬性沒有順序。所以經過for-in循環輸出的屬性名的順序是不可預測的。
注意:建議在使用for-in以前,先檢測確認該對象的值不是null或undefined。

3.6.6 label語句

使用label語句能夠再代碼中添加標籤,以便未來使用。

start: for (var i = 0; i < count; i++){
    alert(i);
}

這個例子中定義的start標籤能夠在未來有breakcontinue語句引用。加標籤的語句通常都要與for語句等循環語句配合使用

3.6.7 break和continue語句

break:

var num = 0;
for(var i = 1; i < 10; i++){
    if(i % 5 == 0){
        break;
    }
    num++;
}
console.log(num);  //4

continue:

var num = 0;
for(var i = 1; i < 10; i++){
    if(i % 5 == 0){
        continue;
    }
    num++;
}
console.log(num);  //8

label能夠和break和continue:

var num = 0;

outermost:  //循環外標籤
for(var i = 1; i < 10; i++){
    for(var j= 0; j < 10; j++){
        if(i == 5 && j == 5){ 
//正常來講break只能跳出一層循環,但外面使用了label語句的標籤outrmost能夠直接跳出所有循環到outermost的位置;
            break outermost;
        }
        num++;
    }
}
console.log(num);  //55

3.6.8 with語句

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

with (expression) statement;

定義with語句的目的主要是爲了簡化屢次編寫同一個對象的工做,以下:

var qs = location.search.substring(1);
var hostName = location.hostname;
var url = localion.href;

上面幾行代碼都包括location對象。若是使用with語句以下:

width(location){
    var qs = search.substring(1);
    var hostName = hostname;
    var url = href;
}

注意:嚴格模式不容許使用with語句,會視爲語法錯誤。with語句大量使用會致使性能降低,同時也會給調試代碼形成困難,所以在開發大型項目時,不建議使用with語句

3.6.9 switch語句

var num = 25;
switch (true){
    case num < 0:
        console.log("0");
        break;
    case num >= 0 && num <= 10:
        console.log("0");
        break;
    default:
        console.log("0");
}

注意:switch語句在比較值時使用的是全等操做符。

3.7 函數

return語句也能夠不帶任何返回值。在這種狀況下,函數在中止執行後將返回undefined值。

推薦作法:是要麼讓函數使用都返回一個值,要麼永遠都不要返回值。不然,若是函數有時候返回值,有時候不反回,會給調試代碼帶來不便

3.7.1 理解參數

在函數體內可使經過arguments對象來訪問這個參數的數組,從而獲取傳遞給函數的每個參數。
經過訪問argments對象的length屬性能夠獲知有多少個參數傳遞給了函數

function doAdd(num1,num2){
    arguments[1] = 10;
    console.log(arguments[1]);        //10
    console.log(num2);                //10
    console.log(arguments[0] + num2); //20
    console.log(arguments.length);    //2  也能夠訪問arguments對象的length屬性能夠獲取有多少個參數傳遞給函數
}
doAdd(10,20);

每次執行這個doAdd()函數都會重寫第二參數,將第二個參數的值修改成10。由於arguments對象中的值會自動反映到對應的命名函數,因此修改arguments[1],也就修改了num2,結果它們的值都會變成10,不過,這並非說讀取這個兩個值會訪問相同的內存空間;它們的內存空間是獨立的,但它們的值會同步。你也能夠反過來修改num2的值效果也是同樣的。

function doAdd(num1,num2){
    num2 = 10;
    console.log(arguments[1]);        //10
}
doAdd(10,20);

arguments對象能夠與命名參數一塊兒使用,如:

function doAdd(num1, num2){
    if(arguments.length == 1){
        console.log(num1 + 10)
    }else{
        console.log(argments[0] + num2);
    }
}
  • arguments對象只是與數組相似(它並非Array的實例).

  • arguments的值永遠與對應命名參數的值保持同步

  • 沒有傳遞值得命名參數將自動被賦予undefined值。

嚴格模式下不容許重寫命名參數或者arguments的值,雖然能夠執行,可是命名參數與arguments對應的值將再也不同步

3.7.2 沒有重載

ECMAScript函數沒有簽名,由於其參數是由包括零或多個值的數組來表示的。而沒有函數簽名,真正的重載是不可能作到的。

最後,若有錯誤和疑惑請指出,多謝各位大哥

若是在ECMAScript中定義了兩個名字相同的函數,則該名字只屬於後定義的函數。

相關文章
相關標籤/搜索