JavaScript學習筆記 - 引用類型

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

  • Object類型前端

  • Array類型java

  • Date類型數組

  • RegExp類型瀏覽器

  • Function類型安全

  • 基本包裝類型數據結構

  • 單體內置對象app

引用類型的值(對象)是引用類型的一個實例。引用類型是一種數據結構,用於將數據和功能組織在一塊兒。也常被稱爲類。引用類型有時候也被稱爲對象定義,由於它們描述的是一類對象所具備的屬性和方法。框架

新對象是使用new操做符後跟一個構造函數來建立的。構造函數自己就是一個函數,只不過該函數是出於建立新對象的目的而定義的。dom

var person = new Object();

這段代碼建立了Object引用類型的一個新實例,而後把該實例保存在變量person中。使用的構造函數是Object,它只爲新對象定義了默認的屬性和方法。

5.1 Object 類型

建立Object實例的方式有兩種。
第一種就是new操做符後跟Object構造函數

var person = new Object();
person.name = "Nicholas";
person.age = 29;

第二種是使用對象字面量表示法。(簡化建立包含大量屬性的對象過程)

var person = {
    name : "Nicholas",
    age : 29
}

使用對象字面量語法時,屬性也可使用字符串

var person = {
    "name" : "Nicholas",
    "age" : 29,
    5 : true
}
//屬性名會自動轉換爲字符串

另外,使用對象字面量語法時,若是留空花括號,則能夠定義只包含默認屬性的方法的對象

var person = {}; //與new Object()相同
person.name = "Nicholas";
person.age = 29;

在經過對象字面量定義對象時,實際上不會調用Object構造函數

對象字面量也是向函數傳遞大量可選參數的首選方式

function displayInfo(args) {
    var output = "";
    if(typeof args.name == "string"){
         output += args.name;
    }
    if(typeof args.age == "number"){
         output += args.age;
    }
    console.log(output)  //Nicholas29,Greg
}
displayInfo({
    name: "Nicholas",
    age: 29
});
displayInfo({
    name: "Greg"
});

這種傳遞參數的模式最適合須要向函數傳入大量可選參數的情形。通常來說,命名參數雖然容易處理,可是有多個可選參數的狀況下就會顯示不夠靈活。最好的作法是對那些必須值使用命名參數,而使用對象字面量來封裝多個可選參數。

通常訪問對象屬性都是點表示法。不過也可使用方括號來訪問對象的屬性

console.log(person["name"]);    //"Nicholas"
console.log(person.name);    //"Nicholas"

//方括號語句主要優勢是能夠經過變量來訪問屬性
var propertyName = "name";
console.log(person[propertyName]); //"Nicholas"

一般,除非必須使用變量來訪問屬性嗎,不然咱們建議使用點表示法。

5.2 Array 類型

與其餘語言不一樣,ECMAScript數組的每一項能夠保存任何類型的數據,能夠用數組第一個位置保存字符串,第二位置保存數值,第三位置保存對象,以此類推。並且ECMAScript數組的大小是能夠動態調整的,便可以隨着數據的添加自動增加以容納新增數據。

建立數組的基本方式有兩種。第一種是使用Array構造函數:

var color = new Array();
var colors = new Array(20);        //將建立length值爲20的數組
var colors2 = new Array("red", "blue", "green");   //建立一個包含3個字符串的數組
var names = new Array("Greg");  //建立一個包含1項的數組;

第二種方式是使用數組字面量表示法:

var colors = ["red", "blue", "green"] //建立一個包含3個字符串的數組
var names = [];  //建立一個空數組
var values = [1,2,];  //不要這樣!這樣會建立一個包含2或3項的數組
var options = [,,,,,];  //不要這樣!這樣會建立一個包含5或5項的數組

與對象同樣,在使用數組字面量表示法時,也不會調用Array構造函數(Firefox3及更早版本除外)

讀取數組和數組length

var colors = ["red", "blue", "green"];
var names = [];    
colors[2] = "black";    //修改第三項
colors[3] = "brown";    //新增第四項
console.log(colors[0]);   //"red"
console.log(colors.length);  //4
console.log(names.length);  //0

//數組length不是隻讀的,經過設置這個屬性能夠從數組的末尾移除項或添加新項
colors.length = 2;        //修改數組的長度爲2,數組就只有2個項了
console.log(colors[2]); //undefined
colors.length = 4;            
console.log(colors[3]);   //undefined;

利用length屬性也能夠方便的在數組末尾添加新項

var colors = ["red", "blue", "green"];
colors[colors.length] = "black";
colors[colors.length] = "brown";

colors[99] = "while";
console.log(colors.length)  //100
//位置5到98實際上都是不存在的訪問他們都將返回undefined

5.2.1 檢測數組

對於一個網頁,或者一個全局做用域而言,使用instanceof操做符就能獲得滿意的結果:

if(value instanceof Array) {
    //...
}

instanceof操做符的問題在於,它假定只有一個全局執行環境。若是網頁中包含多個框架,那實際上就存在兩個以上不一樣的全局執行環境,從而存在兩個以上不一樣版本的Array構造函數。若是你從一個框架向另外一個框架傳入一個數組,那麼傳入的數組與在第二個框架中原生建立的數組分別具備各自不一樣的構造函數。

爲了解決這個問題,ECMAScript5新增了Array.isArray()方法。這個方面目的是最終肯定某個值究竟是不是數組,而無論它是在哪一個全局執行環境中建立的。

if(Array.isArray(value)){
    //...
}

注意:不建議使用instanceof可能會出現異常,推薦使用Array.isArray方法

5.2.2 轉換方法

全部對象都具備toLocaleString()toString()valueOf()方法。數組調用toString()方法會返回由數組中每一個值得字符串形式拼接而成的一個以逗號分隔的字符串,調用valueOf()返回的仍是數組。

var colors = ["red", "blue", "green"];
console.log(colors.toString());   //red,blue,green
console.log(colors.valueOf());    //返回整個數組
console.log(colors);               //返回整個數組
alert(colors.valueOf());          //red,blue,green
alert(colors);                      //red,blue,green

因爲alert()要接收字符串參數,因此它會在後臺調用toString()方法。

使用join()方法,則可使用不一樣的分隔符來構建這個字符串。join()方法值接收一個參數,即用做分隔符的字符串,而後返回包含全部數組項的字符串。

var colors = ["red", "green", "blue"];
alert(colors.join(","));   //red,green,blue
alert(colors.join("||"));  //red||green||blue

若是數組中的某一項值是null或者undefined,那麼該值在join()、toLocaleString()、toString()、valueOf()方法返回的結果中以空字符串表示。

5.2.3 桟方法 和 5.2.4隊列方法

桟方法

在桟中項的插入(叫作推入)移除(叫作彈出),只發生在一個位置——桟的頂部。ECMAScript爲數組專門提供了push()pop()方法,以便實現相似桟的行爲。

push()方法能夠接受任意數量的參數,把它們逐個添加到數組末尾,並返回修改後數組的長度。而pop()方法則從數組末尾移除最後一項,減小數組的length值,而後返回移除的項(值)。

隊列方法

shift()方法可以移除數組中的第一個項並返回該項,同時將數組長度減1。結合使用shift()push()方法,可使用隊列同樣使用數組

ECMAScript還爲數組提供了一個unshift()方法。unshift()shift()的用途相反,它能在數組前端添加任意個項並返回數組的長度。所以同時使用unshift()pop()方法,能夠從相反方向來模擬隊列,即在數組前端添加項,從數組末端移除項。

//push
var colors = new Array();                    //建立一個數組
var count = colors.push("red", "green");    //推入兩項(從後推入)
console.log(count);                            //2
count = colors.push("black");                //推入一項(從後推入)
console.log(count);                            //3
console.log(colors);                        //["red","green","black"]

//pop
var item = colors.pop();                    //取得最後一項
console.log(item);                          //"black"
console.log(colors.length);                 //2
console.log(colors);                        //["red","green"]

//shift
var shit = colors.shift();                    //取得第一項
console.log(shit);                          //"red"
console.log(colors.length);                 //1
console.log(colors);                        //["green"]

//unshift
var unshit = colors.unshift("red","blue");  //推入兩項(從前推入)     
console.log(unshit);                           //3
console.log(colors);                        //["red","blue","green"]

5.2.5 重排序方法

reverse()sort()能夠用來對數組進行重排序。
reverse()方法會反轉數組項的順序。

sort()方法會調用數組中每一項的toString()方法,並根據返回的字符串來對整個數組進行升序的排序,顯然大部分狀況下這種默認行爲都不是咱們所須要的。因此,咱們能夠傳入一個比較函數做爲sort()方法的參數,以便肯定排序的順序。

var num = [0, 5, 1, 10, 15];
num.sort();
alert(num);        //結果並不是是0,1,5,10,15 而是0,1,10,15,5. 緣由是sort比較的是字符串

/* 所以,sort()方法能夠接收一個比較函數做爲參數,以便咱們指定哪一個值位於哪一個值的前面
** 比較函數接收兩個參數,若是第一個參數應該位於第二個參數以前則返回一個負數,相等返回0,在以後就返回正數
*/
function compare(value1, value2){
    return value2 - value1; //降序則改成value1 - value2;
}

var num = [0, 5, 1, 10, 15];
num.sort(compare);
alert(num);//0,1,5,10,15
//若只是想反轉數組,而不用排序就用reverse()
var num = [0, 5, 1, 10, 15];
num.reverse();
alert(num);//15,10,1,5,0

5.2.6 操做方法

  • concat():用於拼接數組

  • slice():用於獲取數組中的某幾個項

  • splice():主要用途是向數組的中部插入項

方法一:concat()方法能夠基於當前數組中的全部項建立個新數組,簡單點就是建立個副本,而後將接受到的參數添加到這個副本的末尾, 原來的數組不會動。

//可接收0個、1個或多個參數,沒有參數就至關於複製當前數組,返回當前數組的副本
//參數如果值,就直接加到副本數組的末尾。參數如果數組,則將數組中的每一項加到副本末尾
var colors = ["red", "green", "blue"];
var colors2 = colors.concat("yello", ["black", "brown"]);

console.log(colors);        //red,green,blue原數組不動
console.log(colors2);        //red,green,blue,yello,black,brown

方法二:slice( )它可以基於當前數組中的一項或多個項建立一個新數組。接收一個參數或者兩個參數,即返回項的起始位置和結束位置。不傳則到末尾。若有2參,結束位置並不包括結束位置所在項(理解從0開始)。注意 不影響原數組

var arr = ["red", "green", "blue", "yello", ""purple];
var arr2 = arr.slice(1);        //由於第二個參數沒有,因此從arr[1]開始獲取後面所有項
var arr3 = arr.slice(1,4);        //截取arr[1]開始到arr[4]前
console.log(arr2);                //green,blue,yellow,purple
console.log(arr3);                //green,blue,yellow

方法三:在數組方法中算是最強大的方法了。它有不少種用法,主要用途是向數組的中部插入項,但使用這種方法的方式則有以下三種。

1.刪除: 能夠刪除任意數量的項,只需指定2個參數: 要刪除第一項的位置和要刪除的項的數目。
舉個栗子,splice(0,2); //刪除數組的前兩項

2.插入: 能夠給指定位置插入任意數量的項。3+個參數,起始位置,0(要刪除的項數爲0項,也就是不刪除)和要插入的項。若是要插入多個項,則把項做爲第4、第五,以至任意多個項。
舉個栗子: splice(2, 0, 「red」, 「yellow」, 「green」); //在位置2依次插入red, yellow,green

3.替換 能夠在指定位置刪除任意多項,且同時刪除任意多項。3個參數。 (startPos, delNum, insertNum) delNum 能夠和insertNum不相等
`舉個栗子: splice(2, 1, 「red」, 「green」);//刪除位置2的1項,再從位置2插入red,green
注意: splice()方法始終返回一個從原始數組刪除的項的數組,若沒有刪除項返回即爲空。
簡單點說,就是刪了什麼就返回了什麼,沒刪就返回空。`

var arr = ["red", "green", "blue"];
var removed = arr.splice(0,1);            //刪除第一項
console.log(arr);                        //green,blue
console.log(removed);                      //red,返回的數組中只包含一項

removed = arr.splice(1, 0, "yellow", "orange");        //從位置1開始插入兩項
console.log(arr);                                    //green,yellow,orange,blue
console.log(removed);                                  //返回的事這個空數組

removed = arr.splice(1, 1, "red", "purole");        //插入兩項,刪除一項
console.log(arr);                                    //green,red,purole,orange,blue
console.log(removed);                                  //yellow,返回的數組中只包含一項

5.2.7 位置方法

  • indexOf():從數組的開頭開始向後查找某一項

  • lastIndexOf():從數組的末尾開始向前查找某一項

兩個方法都返回要查找的項在數組的索引位置,或者在沒找到的狀況下返回- 1

5.2.8 迭代方法

ECMAScript5爲數組定義了5個迭代方法。每一個方法都接收兩個參數: 要在每一項上運行的函數和運行該函數的做用域對象(可選)—-影響this的值。每一項運行的函數包含三個參數: 數組項的值、該項在數組中的位置和數組對象自己。如下是五個方法的做用

  • every(): 對數組中每一項運行指定函數,若是該函數每一項都爲true,則返回true,不然false。

  • filter(): 對數組中每一項運行指定函數, 返回該函數會返回true的項組成的數組(篩選出true的項)

  • forEach(): 對數組中每一項運行指定函數, 沒有返回值。

  • map(): 對數組中每一項運行指定函數, 返回每次函數調用的結果組成的數組

  • some(): 對數組中每一項運行指定函數, 若是該函數對任一項返回true就返回true
    以上方法都不會改變原數組的值。

方法的理解:

  • every() 能夠理解成 &&,全爲真則真

  • filter() 篩選,篩選出真的項組成的數組,

  • forEach() 能夠遍歷數組爲數組的每一個項添加方法

  • map() 映射 無論結果是什麼,都返回一個由結果組成的數組,並不僅是true false

  • some 能夠理解 || 或操做,有一個爲真則爲真

5.2.9 歸併方法

都接受兩個參數:一個在每一項上都調用的函數和做爲歸併基礎的初始值。傳個reduce和reduceRight()的函數都接受4個參數:前一個值、當前值,項的索引和數組對象。

  • reduce(): 從數組第一項開始,逐個遍歷到最後一項,能夠用來數組求和

  • reduceRight(): 從數組最後一項開始,逐個遍歷到第一項,能夠用來數組求和

這兩個方法都會迭代數組的全部項,而後構建一個最終返回的值。

//能夠用來求和
var arr = [1,2,3,4,5];
var sum = arr.reduce(function(prev, cur, index, array){
    return prev + cur;
})
console.log(sum);   //15

5.5 Function類型

函數是Function類型的實例,函數是對象,所以函數名實際上也是一個指向函數對象的指針,不會與某個函數綁定。

//函數聲明語法定義函數
function sum (num1, num2){
    return num1 + num2
};

//函數表達式定義函數
var sum = function sum (num1, num2){
    return num1 + num2
};

//使用Function構造函數
var sum = new Function("num1", "num2", "return num1 + num2");  //不推薦會致使解析兩次代碼

一個函數可能會有多個名字:

function sum (num1, num2){
    return num1 + num2
};

console.log(sum(10,10));  //20

var anotherSum = sum;        //此時,anotherSum和sum的指針都指向了同一個函數
console.log(anotherSum(10,10));  //20

sum = null                    //設爲null指針就沒了和函數斷絕關係
console.log(anotherSum(10,10));  //20

注意:使用不帶圓括號的函數名是訪問函數指針,而非調用函數

5.5.1 沒有重載(深刻理解)

兩個同名函數,後面的函數會覆蓋前面的函數

5.5.2 函數聲明與函數表達式

alert(sum(10,10));
function sum(num1, num2){
    return num1 + num2;
}

以上代碼徹底能夠正常運行,由於在代碼開始執行以前,解析器就已經經過一個名爲函數聲明提高的過程,讀取並將函數聲明添加到執行環境中。對代碼求值時,JavaScript引擎在第一遍會聲明函數並將它們放在源代碼樹的頂部。

alert(sum(10,10));
var sum = function sum(num1, num2){
    return num1 + num2;
}

這段會錯誤,緣由是函數位於一個初始化語句中,而不是一個函數聲明。

5.5.3 做爲值得函數

由於ECMAScript中的函數名自己就是變量,因此函數也能夠做爲值來使用。也就是說,不只能夠像傳遞參數同樣把一個函數傳遞給另外一個函數,並且能夠將一個函數做爲另外一個函數的結果返回。

function createComparisonFunction(proertyName) {
    return function(obj1, obj2) {
        var val1 = obj1[proertyName];
        var val2 = obj2[proertyName];
        if(val1 < val2){
            return -1;
        }else if(val1 > val2){
            return 1;
        }else{
            return 0;
        }
    }
}

var data = [{
    name: "Jason",
    age: 20
}, {
    name: "Cor",
    age: 30
}];

data.sort(createComparisonFunction("name");
console.log(data[0].name);                  //Cor
data.sort(createComparisonFunction("age"));
console.log(data[0].name);                  //Jason

5.5.4 函數的內部屬性

在函數內部,有兩個特殊的對象:argumentsthis

  • arguments的主要用途是保存函數參數但這個對象還有名叫callee的屬性、該屬性是一個指針,指向擁有這個arguments對象的函數。

function factorial(num) {
    if(num <= 1){
        return 1;
    }else{
        //return num * factorial(num-1)     //這個函數的執行與函數名factorial牢牢耦合在一塊兒
        return num * arguments.callee(num-1);   //解除耦合
    }
};
var trueFactorial = factorial;
factorial = function(){
    return 0;
};
console.log(trueFactorial(5))   //120
console.log(factorial(5))         //0

函數內部的另外一個特殊對象是thisthis引用的是函數執行的環境對象——或者也能夠說this值(當在網頁的全局做用域中調用函數時,this對象引用的就是window)

window.color = "red";
var o = { color : "blue" };

function sayColor() {
    console.log(this.color);
}

sayColor();      //"red"

o.sayColor = sayColor;        //把sayColor函數賦給對象o
o.sayColor();    //"blue"    //this的引用是對象o

ECMAScript5也規範化了另外一個函數對象的屬性:caller。這個屬性中保存着調用當前函數的函數的引用,若是是在全局做用域中調用當前函數,它的值爲null

function outer(){
    inner();
}

function inner(){
    console.log(arguments.callee.caller);    //爲了實現更鬆散的耦合
}

outer();

注意:當函數在嚴格模式下運行是,訪問arguments.callee會致使錯誤。ECMAScript 5 還定義了arguments.caller屬性,但在嚴格模式下訪問它也會致使錯誤,而在非嚴格模式下這個屬性始終是undefined。定義arguments.callee屬性是爲了分清arguments.caller和函數的caller屬性。以上變化都是爲了增強這門語言的安全性,這樣第三方代碼就不能在相同的環境裏窺視其餘代碼了。
嚴格模式還有一個限制:不能爲函數的caller屬性賦值,不然會致使錯誤。

5.5.5 函數屬性和方法

ECMAScript的函數也是對象,所以函數也有屬性和方法。每一個函數包含兩個屬性: lengthprototypelength屬性表示函數的參數數量

function jason(a, b, c) {};
console.log(jason.length); //3;

對於ECMAScript的引用類型而言,prototype是保存它們全部實例方法的真正所在。toString()valueOf()等方法實際上都保存在prototype名下,只不過是經過各自對象的實例訪問。在建立自定義引用類型以及實現繼承時,prototype屬性的做用是極爲重要的。在ECMAScript5中,prototype屬性是不可枚舉的,所以使用for-in沒法發現。

每一個函數都包含兩個非繼承而來的方法:apply() call()。這兩個方法的用途都是在特定的做用域中調用函數,實際上等於設置函數體內this對象的值。首先,apply()方法接收兩個參數:一個是在其中運行的做用域,另外一個是參數數組。其中第二個參數可使Array的實例,也能夠是arguments對象。

1.apply():

/*定義一我的類*/
function Person(name,age)
{
    this.name=name;
    this.age=age;
}
/*定義一個學生類*/
function Student(name,age,grade)
{
    Person.apply(this,arguments);
    this.grade=grade;
}
//建立一個學生類
var student=new Student("qian",21,"一年級");
//測試
alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);
//你們能夠看到測試結果name:qian  age:21  grade:一年級
//學生類裏面我沒有給name和age屬性賦值啊,爲何又存在這兩個屬性的值呢,這個就是apply的神奇之處.

分析:
Person.apply(this,arguments);
this:在建立對象在這個時候表明的是student
arguments:是一個數組,也就是["qian」,」21」,」一年級」];
通俗的說:student去執行Person這個類裏面的內容,在Person這個類裏面存在this.name等之類的語句,這樣就將屬性建立到了student對象裏面

2.call():

call()法與apply()方法做用相同,它們的區別僅在於接受參數的方式不一樣。在使用call()方法時,傳遞給函數的參數必須逐個列舉出來

在上面Student函數裏面能夠將apply中修改爲以下:

function Student(name,age,grade)
{
    Person.call(this,name,age);
    this.grade=grade;
}
//效果是同樣的

3.什麼狀況下用apply,什麼狀況下用call

在給對象參數的狀況下,若是參數的形式是數組的時候,好比apply示例裏面傳遞了參數arguments,這個參數是數組類型,而且在調用Person的時候參數的列表是對應一致的(也就是Person和Student的參數列表前兩位是一致的) 就能夠採用 apply , 若是個人Person的參數列表是這樣的(age,name),而Student的參數列表是(name,age,grade),這樣就能夠用call來實現了,也就是直接指定參數列表對應值的位置(Person.call(this,age,name,grade));

4.apply的一些其餘巧妙用法

細心的人可能已經察覺到,在我調用apply方法的時候,第一個參數是對象(this), 第二個參數是一個數組集合, 在調用Person的時候,他須要的不是一個數組,可是爲何他給我一個數組我仍然能夠將數組解析爲一個一個的參數,這個就是apply的一個巧妙的用處,能夠將一個數組默認的轉換爲一個參數列表([param1,param2,param3]) 轉換爲(param1,param2,param3) 這個若是讓咱們用程序來實現將數組的每個項,來裝換爲參數的列表,可能都得費一會功夫,藉助apply的這點特性,因此就有了如下高效率的方法:

  • Math.max 能夠實現獲得數組中最大的一項
    由於Math.max 參數裏面不支持Math.max([param1,param2]) 也就是數組

可是它支持Math.max(param1,param2,param3…),因此能夠根據剛纔apply的那個特色來解決 var max=Math.max.apply(null,array),這樣輕易的能夠獲得一個數組中最大的一項(apply會將一個數組裝換爲一個參數接一個參數的傳遞給方法)
這塊在調用的時候第一個參數給了一個null,這個是由於沒有對象去調用這個方法,我只須要用這個方法幫我運算,獲得返回的結果就行,.因此直接傳遞了一個null過去

var nums = [3, 2, 1, 5, 4];
var max = Math.max.apply(null, nums);
console.log(max);  //5
  • Math.min 能夠實現獲得數組中最小的一項

var nums = [3, 2, 1, 5, 4];
var min = Math.min.apply(null, nums);
console.log(min);  //1
  • Array.prototype.push 能夠實現兩個數組合並
    一樣push方法沒有提供push一個數組,可是它提供了push(param1,param,…paramN) 因此一樣也能夠經過apply來裝換一下這個數組,即:

var nums = [1, 2, 3, 4, 5];
var nums2 = [6, 7, 8, 9];
var max = Array.prototype.push.apply(nums, nums2);
console.log(nums);  //1,2,3,4,5,6,7,8,9

也能夠這樣理解nums調用了push方法,參數是經過apply將數組裝換爲參數列表的集合.

一般在什麼狀況下,可使用apply相似Math.min等之類的特殊用法:

通常在目標函數只須要n個參數列表,而不接收一個數組的形式([param1[,param2[,…[,paramN]]]]),能夠經過apply的方式巧妙地解決這個問題!

5.bind()

ECMAScript5還定義了一個方法:bind()。這個方法會建立一個函數的實例,其this值會被綁定到傳給bind()函數的值。

window.color = "red";
var o = { color : "blue" };

function sayColor() {
    console.log(this.color);
}
var objectSayColor = sayColor.bind(o);        
//sayColor()調用bind()並傳入對象o,並建立了objectSayColor函數。objectSayColor()函數的this值等於o

objectSayColor();        //blue

每一個繼承的toLocaleString()toString()方法始終都返回函數的代碼。另一個繼承的valueOf()方法一樣只返回函數代碼。

5.6 基本包裝類型

爲了便於操做基本類型值,ECMAScript還提供了3個特殊的引用類型:BooleanNumberString。這些類型與本章介紹的其餘引用類型類似,但同時也具備與各自的基本類型相應的特殊行爲。實際上,每當讀取一個基本類型值的時候,後臺就會建立一個對應的基本包裝類型的對象,從而讓咱們可以調用一些方法來操做這些數據。

var s1 = "some text";        //基本類型值
var s2 = s1.substring(2);    //調用了s1的substring()方法,結果保存s2

基本類型值不是對象,於是從邏輯上它們不該該有方法(但它們確實有方法)。其實,後臺已經自動完成了一系列的處理。當第二行代碼訪問s1時,訪問過程處於一種讀取模式,也就是要從內存中讀取這個字符串的值。而在讀取模式訪問字符串時,後臺都會自動完成下列處理。
(1)建立String類型的一個實例;
(2)在實例上調用指定的方法;
(3)銷燬這個實例。
能夠將以上三個步驟想象成是執行了下列代碼。

var s1 = new String("some text");    //建立String類型的一個實例;
var s2 = s1.substring(2);            //在實例上調用指定的方法;
s1 = null;                             //銷燬這個實例。

通過此番處理,基本的字符串值就變得跟對象同樣了。並且,上面的三個步驟也分別適用於BooleanNumber類型對於的布爾值和數字值。

引用類型與基本包裝類型的主要區別就是對象的生存期。使用new操做符建立的引用類型的實例,在執行流離開當前做用域以前都一直保存在內存中。而自動建立的基本包裝類型的對象,則只存在於一行代碼的執行瞬間而後當即被銷燬。這意味着咱們不能在運行時爲基本類型值添加屬性和方法。

var s1 = "some text";
s1.color = "red";
alert(s1.color);   //undefined        第二行建立的String對象在執行這行時已經被銷燬

對基本包裝類型的實例調用typeof會返回"object",並且全部基本包裝類型的對象都會被轉換爲布爾值的true

Object構造函數也會像工廠方法同樣,根據傳入值的類型返回相應的基本類型包裝的實例。

var obj = new Object("some text");    //把字符串傳給Object構造函數,就會建立String實例;而傳入數值會獲得Number的實例,傳入布爾值參數就會獲得Boolean的實例。
console.log(obj instanceof String);   //true

要注意的是,使用new調用基本包裝類型的構造函數,與直接調用同名的轉型函數是不同的。例如:

var value = "25";
var number = Number(value);      //轉型函數   變量number保存的是基本類型的值25
console.log(typeof number);   //number

var obj = new Number(value);  //構造函數   變量obj保存的是Number的實例
console.log(typeof obj);      //object

儘管不建議顯式的建立基本包裝類型的對象,但它們操做基本類型值的能力仍是至關重要的。而每一個2基本包裝類型都提供了操做響應值的便捷方法。

5.6.1 Boolean類型

Boolean類型是與布爾值對應的引用類型。Boolean類型的實例重寫了valueOf()方法,返回基本類型值true或false;重寫了toString()方法,返回字符串"true"和"false"。

var falseObject = new Boolean(false);
var result = falseObject && true;        //布爾表達式中的全部對象都會被轉換爲true。所以表達式是true && true
console.log(result);                    //true

var falseValue = false;
result = falseValue && true;
console.log(result)                      //false

alert(typeof falseObject);                //object
alert(typeof falseValue);                 //boolean
alert(falseObject instanceof Boolean);  //true
alert(falseValue instanceof Boolean);   //false

建議永遠不要使用Boolean對象

5.6.2 Number類型

Number是與數字值對於的引用類型。要建立Number對象,能夠在調用Number構造函數時向其中傳遞相應的數值。

var numberObject = new Number(10);

與Boolean類型同樣。Number類型也重寫了valueOf()toLocaleString()toString()方法。重寫後的valueOf()方法返回對象表示的基本類型數值,另外兩個方法則返回字符串形式的數值。

Number類型還提供了一些用於將數值格式化爲字符串的方法。

toFixed()

toFixed()方法會按照知指定的小數位返回數值的字符串表示:

var num = 10.005;
console.log(num.toFixed(2));  //"10.01"

可以自動舍入的特性,使得toFixed()方法很適合處理貨幣值。不一樣瀏覽器的給這方法的舍入規則可能會有所不一樣。

toExponential()

toExponential()方法返回以指數表示法(e表示法)表示的數值得字符串形式。toExponential()也接收一個參數,該參數也是指定輸出結果中的小數位數。

var num = 10;
console.log(num.toExponential(1)); //"1.0e+1"

toPrecision()

對於一個數值來講,toPrecision()方法可能會返回固定大小(fixed)格式,也可能返回指數(exponential)的格式;具體規則是看哪一種格式最合適。這個方法接收一個參數,即表示數值的全部數字的位數(不包含指數部分)。

var num = 99;
console.log(num.toPrecision(1));    //"1e+2"
console.log(num.toPrecision(2));    //"99"
console.log(num.toPrecision(3));    //"99.0"

與Boolean對象雷士,Number對象也之後臺方式爲數值提供了重要的功能。但與此同時,咱們仍然不建議直接實例化Number類型,而緣由與顯式建立Boolean對象同樣。具體來說,就是在使用typeof和instanceof操做符測試基本類型數值與引用類型數值時,獲得的結果徹底不一樣,以下

var numberObject = new Number(10);
var numberValue = 10;
alert(typeof numberObject);               //"object"
alert(typeof numberValue);                  //"number"
alert(numberObject instanceof Number);  //true
alert(numberValue instanceof Number)    //false

5.6.3 String類型

String類型是字符串對象包裝類型。可使用String構造函數建立

var stringObject = new String("hello world");

String對象的方法也能夠在全部基本的字符串值中訪問到。其中,繼承的valueOf()toLocaleString()toString()方法,都返回對象所表示的基本字符串值。

String類型每一個實例都有一個length屬性

var stringValue = "hello world";
console.log(stringValue.length); //"11"

String類型提供了不少方法,用於輔助完成對ECMAScript中字符串的解析和操做。

1. 字符方法

兩個用於訪問字符串中特定字符的方法是:charAt()charCodeAt()

var stringValue = "hello world";
console.log(stringValue.charAt(1));     //"e"   返回字符串1的位置的字符
console.log(stringValue.charCodeAt());  //"101" 返回字符串1的位置的字符編碼
console.log(stringValue[1]);               //"e"   返回字符串1的位置的字符

2. 字符串操做方法

操做字符串的方法:

  • concat() 用於將以或多個字符串拼接起來

var stringValue "hello ";
var result = stringValue.concat("world", "!");  能夠接收多個參數
console.log(result);        //"hello world"
console.log(stringValue);    //"hello"

ECMAScript還提供了三個基於子字符串建立新字符串的方法:slice()substr()substring()這三個方法都會返回被操做字符串的一個子字符串,並且也都接受一或兩個參數。第一個參數指定子字符串的開始位置,第二個參數(在指定的狀況下)表示字符串到哪結束。slice()substring()指第二個參數指定的是子字符串最後一個字符後面的位置。而substr()的第二個參數指定的則是返回的字符個數。若是沒有給這些方法傳遞第二個參數,則將字符串的長度做爲結束位置。這三個方法不會修改字符串自己的字——只返回一個基本類型的字符串字。

var stringValue = "hello world";
console.log(stringValue.slice(3));           //"lo world"
console.log(stringValue.substring(3));      //"lo world"
console.log(stringValue.substr(3));          //"lo world"
console.log(stringValue.slice(3, 7));          //"lo w"
console.log(stringValue.substring(3, 7));   //"lo w"
console.log(stringValue.substr(3, 7));       //"lo worl"

console.log(stringValue.slice(-3));               //"rld"           slice會將傳入的負值和字符串想家
console.log(stringValue.substring(-3));          //"hello world"    substring會把全部負值轉換爲0
console.log(stringValue.substr(-3));              //"rld"           substr將負的第一個參數加上字符串的長度
console.log(stringValue.slice(-3, -4));          //"lo w"        
console.log(stringValue.substring(-3, -4));       //"hel"
console.log(stringValue.substr(-3, -4));           //""            轉換爲0等於包含0個字符串

3.字符串位置方法

  • indexOf() (從前日後)從一個字符串中搜索給定的子字符串,而後返回子字符串的位置。
    - lastIndexOf() (從後往前)

4.trim()方法

ECMAScript5爲全部字符串定義了trim()方法。這個方法會建立一個字符串的副本,刪除前置及後綴的全部空額而後返回結果

  • trimLeft() 刪除字符串開頭空格

  • trimRight() 刪除字符串末尾空格

5.字符串大小寫轉換方法

  • toLocaleUpperCase() —— 轉換大寫

  • toUpperCase() —— 轉換大寫

  • toLocaleLowerCase() —— 轉換小寫

  • toLowerCase() —— 轉換小寫

6.字符串的模式匹配方法

  • match()匹配

  • search()查找

  • replace()替換

  • split()分割字符串

7.localeCompare()方法

這個方法比較兩個字符串

8.fromCharCode()方法

String構造函數自己還有一個靜態方法。這個方法接收一或多個字符編碼,而後把它轉換爲字符串。

5.7 單體內置對象

ECMA-262對內置對象的定義是:「由ECMAScript實現提供的、不依賴於宿主環境的對象,這些對象在ECMAScript程序執行以前就已經存在了」意思就是說,開發人員沒必要顯式地實例化內置對象,由於它們已經實例化了。前面咱們已經介紹了大多數的內置對象,例如Object、Array和String。ECMA-262還定義了兩個單體內置對象:Global和Math。

注:每一個內置對象(built-in object)都是原生對象(Native Object),一個內置的構造函數是一個內置的對象,也是一個構造函數。

5.7.1 Global對象

Global(全局)對象能夠說是ECMAScript中最特別的一個對象了,由於你無論從什麼角度看,這個對象都是不存在的。不屬於任何其餘對象的屬性和方法,最終都是它的屬性和方法。全部在全局做用域定義的屬性和函數,都是Global對象的屬性。諸如isNaN()isFinite()parseInt()以及parseFloat(),實際上全都是Global對象的方法

1.URI 編碼方法

  • encodeURI()——編碼

  • encodeURIComponent()——編碼

  • encodeURI()——解碼

  • encodeURIComponent()——解碼

2.eval()方法

Javascript 的 eval 函數能夠在當前做用域執行一段包含 Javascript 代碼的字符串。
然而,eval 函數只有在當前做用域中直接被調用而且被調用的函數名爲 eval 纔會被執行。
eval 函數的使用應該被避免,99.9% 使用 eval 函數所實現的功能均可以經過不使用 eval 函數來實現。

eval 函數應該儘量地避免使用。任何使用 eval 函數的代碼都應該被質疑,遠離eval

3.Global 對象的屬性

特殊的值undefined、NaN以及Infinity都是Global對象的屬性。全部原生引用類型的構造函數,象Object和Function,也都是Global對象的屬性。

4.window 對象

ECMAScript雖然沒有指出如何直接訪問Global對象,但Web瀏覽器都是將這個全局對象做爲window對象的一部分加以實現的。所以全局做用域中聲明的全部變量和函數,就都成爲了window對象的屬性。

JavaScript中的window對象除了扮演ECMAScript規定的Global對象的角色外,還承擔了不少別的任務。

另外一種取得Global對象的方法:

var global = function(){
    return;
}

5.7.2 Math對象

1.Math對象的屬性

Math對象包含的屬性大都是數學計算中可能會用到的一些特殊值

2min()和max()方法

能夠找到最大值max和最小值min
用於數組

var values = [1, 2, 3, 5, 4];
var max = Math.max.applu(null, values);  //5

3.舍入方法

  • Math.ceil() 執行向上舍入,即它老是將數值向上舍入爲最接近的整數

  • Math.floor() 執行向下舍入,即它老是將數值向下舍入爲最接近的整數

  • Math.round() 執行標準舍入,即它老是將數值四捨五入爲最接近的整數

console.log(Math.ceil(25.9));   //26     ceil(25.5)——26    ceil(25.1)——26
console.log(Math.round(25.9));  //26     round(25.5)——26   round(25.1)——25
console.log(Math.floor(25.9));  //25     floor(25.5)——25   floor(25.1)——25

4.random()方法

隨機數

值 = Math.floor(Math.random() * 可能值得總數 + 第一個可能的值)

//隨機數1-10之間
var num = Math.floor(Math.random() * 10 + 1);
//2-10
var num = Math.floor(Math.random() * 9 + 2);

//計算數值
function selectFrom(lowerValue, upperValue) {
    var choices = upperValue - lowerValue + 1;
    return Math.floor(Math.random() * choices + lowerValue);
}
//2-10
var num = selectFrom(2, 10);

//隨機抽取
var colors = ["red", "green", "blue"];
var color = colors[selectFrom(0, colors.lenght-1)];  //0到數組的長度

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

相關文章
相關標籤/搜索