JavaScript 語法簡述

一、比較運算「==」和「===」區別:
「==」比較,他會自動轉換數據類型再比較,不少時候會獲得很是詭異的結果。
「===」比較,他不會自動轉換數據類型,若是數據類型不一致,返回false。若是類型一致,再比較。
「==」比較是JavaScrpit早期語言設計存在設計缺陷只是爲了兼容而保留,因此,如今應該儘量使用「===」,而儘可能避免使用「==」。javascript

二、NaN是特殊的數值。java

NaN與全部其餘值都不相等,包括它本身,因此判斷是否爲NaN的方法是經過isNaN()函數:python

NaN === NaN; //false
var a = NaN;
a === NaN;   //false
isNaN(a);   //true

三、數組索引以0爲起始web

四、JavaScript對象編程

var person = {
    name: 'Bob',
    age: 20,
    tags: ['js', 'web', 'mobile'],
    city: 'Beijing',
    hasCar: true,
    zipcode: null
};

訪問對象屬性使用「對象變量名.屬性名」。windows

五、strict模式:強制要求使用var 申明變量。數組

在代碼第一行寫上:瀏覽器

'use strict';

嚴格模式爲ES5後出現,因此,IE6,7,8,9 均不支持嚴格模式。閉包

六、字符串可使用'或者"括起來,若是字符串內同時包含'和"能夠用轉義字符\來標識。app

轉義字符\自己在字符串中也要轉移因此,字符串中\\表示\,描述windows中的路徑時要注意。
可使用\x##形式表示ASCII字符,還能夠用\u####表示一個Unicode字符:

'use strict';
var i = '\u4e2d\u6587\x41';
console.log(i);

ES6標準新增:
能夠用反單引號括起可實現多行字符串

var a = `這是第一行
這是第二行
這是第三行`;
console.log(a);
/*
這是第一行
這是第二行
這是第三行
*/

模板字符串

var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}歲了!`; //注意是反單引號
console.log(message);

七、操做字符串

.length

var s = 'Hello, world!';
s.length;

要獲取字符串某個位置的支付可使用相似數組下標的操做,索引號從0開始:

var s = 'Hello, world!';
s[0];

可是,這種方式不能用來修改字符串。

.toUpperCase()

字符串變大寫字符串

var s = 'Hello';
s = s.toUpperCase(); // 返回'HELLO'
console.log(s);

.toLowerCase()

字符串變小寫字符串

var s = 'Hello';
s = s.toLowerCase(); // 返回'hello'
console.log(s);

.indexOf()

指定字符串出現的位置,以0爲起始,沒找到返回-1;

var s = 'hello, world';
var i1 = s.indexOf('world'); // 返回7
var i2 = s.indexOf('World'); // 沒有找到指定的子串,返回-1
console.log(`第一位置:${i1},第二位置:${i2}`);

.substring()

根據索引獲取子串

var s = 'hello, world'
var sub1 = s.substring(0, 5); // 從索引0開始到5(不包括5),返回'hello'
var sub2 = s.substring(7); // 從索引7開始到結束,返回'world'
console.log(`第一:${sub1},第二:${sub2}`);

.split(seq)

根據分隔符將字符串分割成數組

var data = "1;3;5";
var ary = data.split(';');

八、數組

數組能夠包含任意數據類型,並經過索引來訪問每一個元素。
要取得數組的長度,直接訪問length屬性:

var arr = [1, 2, 3.14, 'Hello', null, ture];
arr.length; //6

注意,直接給數組的length賦一個新的值會致使數組大小的變化:

var arr = [1, 2, 3];
arr.length;
arr.length = 6;
arr;  // arr變爲[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;
arr; //arr變爲[1, 2]

大多數其餘編程語言不容許直接改變數組的大小,越界訪問索引會報錯。然而,JavaScript的Array卻不會有任何錯誤。在編寫代碼時,不建議直接修改數組的大小,訪問索引時要確保索引不會越界。

.indexOf()

與String相似,數組也能夠經過indexOf()來搜索一個指定的元素的位置:

var arr = [10, 20, '30', 'xyz'];
arr.indexOf(10); //元素10的索引爲0
arr.indexOf(20); //元素20的索引爲1
arr.indexOf(30); //元素30的沒有找到,返回-1
arr.indexOf('30'); //元素'30'的索引爲2

注意了,數字30和字符串'30'是不一樣的元素

.slice()

slice()就是對應String的substring()版本,它截取數組的部分元素,而後返回一個新的數組:

var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
arr.slice(0, 3); // 從索引0開始,到索引3結束,但不包括索引3:['A', 'B', 'C']
arr.slice(3); // 從索引3開始到結束:['D', 'E', 'F', 'G']

若是不給slice()傳遞參數,他會從頭至尾截取全部元素。利用這一點,咱們能夠很容易地複製一個數組。

var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var aCopy = arr.slice();
aCopy; //['A', 'B', 'C', 'D', 'E', 'F', 'G']
aCopy === arr; //false

.push()和.pop()

push向數組的末尾添加一到多個元素,pop則把數組的最後一個元素刪除掉:

var arr = [1, 2];
arr.push('A', 'B'); // 返回數組新的長度:4
arr; // [1, 2, 'A', 'B']
arr.pop(); // pop()返回'B'
arr; // [1, 2, 'A']
arr.pop(); arr.pop(); arr.pop() // 連續pop 3次
arr; // []
arr.pop(); // 空數組繼續pop不會報錯,而是返回undefined
arr; // []

.unshift()和.shift()

若是要往數組的頭部添加若干元素,使用unshift()方法,shift()方法則把數組的第一個元素刪掉。

var arr = [1, 2];
arr.unshift('A', 'B'); // 返回 Array新的長度:4
arr; // ['A', 'B', 1, 2]
arr.shift(); // 'A'
arr; // ['B', 1,  2]
arr.shift(); arr.shift(); arr.shift();  // 連續shift 3次
arr; //[]
arr.shift(); // 空數組繼續shift不會報錯,而是返回undefined
arr; // []

.sort()

sort能夠對當前數組進行排序,它會直接修改當前數組的元素位置,直接調用時,按照默認順序排序。

var arr = ['B', 'C', 'A'];
arr.sort();
arr; // ['A', 'B', 'C']

.reverse()

reverse把整個數組的元素反轉

var arr = [1, 2, 3];
arr.reverse();
arr; //[3, 2, 1]

.splice()

splice方法是修改數組的萬能方法,它能夠從指定的索引開始刪除若干元素,而後再從該位置添加若干元素

var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 從索引2開始刪除3個元素,而後在索引2開始添加兩個元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回刪除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只刪除,不添加:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只添加,不刪除,至關於插入:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],由於沒有刪除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 在數組尾部追加
arr.splice(5, 0, 'Yahoo', 'AOL'); // 返回[]
arr; // ['Microsoft',  'Apple',  'Google',  'Facebook',  'Oracle', 'Yahoo', 'AOL']

.concat()

concat方法把當前的數組和另一個數據包括數組連接起來,並返回一個新的數組

var arr = ['A', 'B', 'C'];
var added = arr.concat([1, 2, 3]);
added; // ['A', 'B', 'C', 1, 2, 3]
arr; // ['A', 'B', 'C']
arr.concat(1, 2, [3, 4]); // ['A', 'B', 'C', 1, 2, 3, 4]

concat方法並無修改當前數組, 而是返回了一個新的數組。

.join()

join方法是一個很是實用的方法,它把當前數組的每一個元素都用指定的字符串鏈接起來,而後返回鏈接後的字符串

var arr = ['A', 'B', 'C', 1, 2, 3]; 
arr.join('-'); // 'A-B-C-1-2-3' 可見數組元素不是字符串將轉換爲字符串後再鏈接

九、多維數組

若是數組的某個元素又是一個數組,則能夠造成多維數組

var arr = [[1, 2, 3], [400, 500, 600], '-'];
var x = arr[1][1];
x; // 500

十、對象

var xiaoming = {
    name: '小明',
    birth: 1990,
    school:  'No.1 Middle School',
    height: 1.70,
    weight: 65,
    score: null
};

注意,最末尾的鍵值對後面不要加','號。

JS用花括號定義一個對象,屬性以鍵值對形式聲明,用逗號隔開。能夠動態的以xxx.newname = value的形式給對象添加屬性。
屬性名稱推薦以變量名規則命名,不要包含特殊字符,'-'號也是特殊字符。訪問不存在的屬性,會返回undefined。

刪除屬性,delete
判斷對象中是否有某個屬性,能夠用in,可是,in判斷的屬性不必定是屬於該對象,也多是繼承獲得的。若是判斷屬性是不是對象自身擁有的,可使用hasOwnProperty()方法。

xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false

十一、條件判斷

if(){
    ......
}else{
    ......
}

建議使用花括號,即便其中只有一條語句。

多行條件判斷

if () {
    ......
} else if () {
    ......
} else {
    ......
}

if的判斷表達式一般是以布爾值true或false來判斷,可是也有用其餘值得狀況。
JavaScript把null、undefined、0、NaN和空字符串''視爲false,其餘值一律視爲true。

十二、循環

傳統for循環

for(let i=1; i<=1000; i++){
    ......
}

若是for循環中的三個表達式都省略,則能夠實現無限循環for(;;){...}。無限循環要用break語句才能退出。

for ... in循環

把一個對象的全部屬性一次循環出來。

var o ={
    name: 'Jack',
    age: 20,
    city: 'Beijing'
};
for (var key in o){
    console.log(key); // 'name', 'age', 'city'
}

數組也是對象,因此當用for...in對數組使用的時候,每一個元素的索引就是屬性

var a = ['A', 'B', 'C'];
for (var i in a){
    console.log(i);
    console.log(a[i]);
}

注意,for...in 對數組的循環獲得的是String而不是Number。

while循環和do...while循環
沒事什麼特別的,略。

1三、Map和Set

ES6規範引入的數據類型。

Map是一組鍵值對,具備極快的查找速度。

var m=new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95
m.set('Bob', 77); // 一個鍵只對應一個值,當對已有鍵設置值時,新值會換掉舊值,Bob 的值變爲 77
m.has('Adam'); // false,檢查是否有鍵'Adam'
m.set('Adam',65); //不存在的鍵,自動增長
m.delete('Adam'); //刪除鍵'Adam'
m.get('Adam'); // undefined

Set是一組鍵的集合,沒有value。鍵不能重複,若是有重複會自動過濾。

var s1 = new Set([1, 2, 3, 4, 3, '3']);
s1; // [1, 2, 3, 4, '3'] 重複的3被過濾掉,注意數字3和字符串3不是重複項
s1.add(6); //增長新key
s1.delete(6);//刪除key

1四、iterable

ES6標準一如的新類型,Array、Map和Set都屬於iterable類型。具備iterable類型的集合能夠經過for ... of循環來遍歷。

'use strict';
var a = [1, 2, 3];
for (var x of a){
    console.log(x);
}

遍歷iterable類型還可使用內置的forEach方法。

var a = ['A', 'B', 'C'];
a.forEach(function(element, index, array) {
    // element: 指向當前元素的值
    // index: 指向當前索引
    // array: 指向Array對象自己
    console.log(element + ', index = ' + index);
}

1五、函數

函數的形式 function 函數名(參數列表){......}
函數也是對象,能夠賦值給變量,而後經過變量調用。
函數容許接收任意個參數。
關鍵字 arguments,是一個參數數組,在函數內部起做用,指向傳入的全部參數,有length屬性,能夠經過下標訪問。

ES6標準引入rest參數,用法

function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 結果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]

foo(1);
// 結果:
// a = 1
// b = undefined
// Array []

注意,函數中return語句要只佔一行,不然可能會出現意想不到的錯誤。

function foo(){
    if(2 > 1){
        return  // JavaScript引擎有一個在行末自動添加分號的機制,這裏至關於return;
                2;
    }
}
foo();
//結果爲undefined

1六、變量做用域

若是一個變量在函數內部進行var聲明,則改變量做用域爲整個函數體,在函數體外不可引用改變量:

'use strict';
function foo() {
    var x =1;
    x = x + 1;
}

x = x + 2; // ReferenceError 沒法在函數體外引用變量x

JavaScript的函數是能夠嵌套的,所以,內部函數能夠訪問外部函數定義的變量,反過來不行:

'use strict';
function foo() {
    var x = 1;
    function bar() {
        var y = x+1; // bar 能夠訪問foo的變量x
    }
    var z = y + 1; // ReferenceError foo不能夠訪問bar的變量y
}

若是內部函數和外部函數定義了同名變量,則內部函數中變量會屏蔽外部函數變量。

變量提高

JavaScript的函數在使用時,會先掃描整個函數體的語句,把全部聲明的變量「提高」到函數頂部:

'use strict';

function foo() {
    var x = 'Hello, '+y; //  由於通過掃描,JavaScript知道y已經聲明瞭,因此不會報錯,可是此時y是沒有值,是undefined
    console.log(x);
    var y = 'Bob';
}
foo();

因此上述的foo函數,至關於:

function foo() {
    var x,y;
    x = 'Hello, '+y;
    console.log(x);
    y = 'Bob';
}

由於JavaScript有這樣的特性,因此咱們在函數內部定義變量時,應該模仿pascal在函數中先聲明全部的變量,在進行使用。

全局做用域

不在任何函數內定義的變量就具備全局做用域。JavaScript默認有一個全局對象window,全局做用域的變量實際上被綁定到window的一個屬性:

'use strict';

var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // 與上一句是同樣的

頂層函數實際上也是一個全局變量並綁定到window對象:

'use strict';

function foo() {
    alert('foo');
}
foo();
window.foo();

JavaScript默認的函數其實也是window的一個變量,咱們能夠經過修改變量達到從新定義默認函數的目的:

'use strict';

var old_alert = window.alert;
window.alert = function() {}
alert('沒法用alert()顯示了');
//恢復alert;
window.alert = old_alert;
alert('又能夠用alert()了');

名字空間

全局變量會綁定到window上,可是咱們在網頁中經常使用多個JavaScript文件,若是這些文件中使用了相同的全局變量,或者定義了相同名字的頂層函數,都會形成命名衝突,並且很難被發現。

因此,爲了減小衝突,咱們能夠吧本身的全部變量和函數所有綁定到一個全局變量中。例如:

var MYAPP = {};

MYAPP.name = 'myapp';
MYAPP.version = 1.0;

MYAPP.foo = function() {
    return 'foo';
};

這樣能夠大大減小全局變量衝突的可能性。

局部做用域

局部做用域上是整個函數內部,而有時須要聲明塊級做用域的變量。ES6引入了新關鍵字let來實現:

'use strict';

function foo() {
    var sum = 0;
    for (let i=0; i<100; i++) {
        sum += i;
    }
    i += 1; // SyntaxError: i再for塊聲明,因此此處錯誤。若是是var則不會出錯。
}

常量

因爲var和lett聲明的是變量,若是要聲明一個常量,在ES6以前是不行的,以往一般用所有大寫的變量來表示這是常量。
ES6標準引入了新的關鍵字const來定義常量,const與let都具備塊級做用域:

'use strict';

const PI = 3.14;
PI = 3; // 某些瀏覽器不報錯,可是無效果
PI; // 3.14

1七、解構賦值

從ES6開始,JavaScript引入瞭解構賦值,能夠同時對一組變量進行賦值。
解構賦值就是直接對多個變量同時賦值:

'use strict';

// 若是瀏覽器支持解構賦值就不會報錯:
var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
// x, y, z分別被賦值爲數組對應元素:
console.log('x = ' + x + ', y = ' + y + ', z = ' + z);

若是數組自己還有嵌套,也能夠經過如下的形式進行解構賦值。

let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
x; // 'hello'
y; // 'JavaScript'
z; // 'ES6'

解構賦值還能夠忽略某些元素:

let [ , ,z] = ['hello', 'JavaScript', 'ES6']; // 忽略前兩個元素, 只對z賦值第三個元素
z; // 'ES6'

若是須要從一個對象中取出若干屬性, 也可使用解構賦值,便於快速獲取對象的指定屬性:

'use strict';

var person ={
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school',
    address: {
        city: 'Beijing',
        street: 'No.1 Road',
        zipcode: '100001'
    }
};
var {name, age, address: {city, zip}} = person;
var {passport: id} = person; // 將屬性passport賦值給變量id
// 分別被賦值爲對應屬性,變量名與屬性名相同
// address 不是變量,而是爲了讓city和zip得到嵌套的address對象的屬性
// passport 不是變量,而是爲了讓變量id得到passport屬性
name; // '小明'
age; // 20
city;  // 'Beijing'
zip; // undefined,由於屬性名是zipcode而不是zip
address; // Uncaught ReferenceError: address is not defined
id; // 'G-12345678'
passport; // Uncaught ReferenceError: passport is not defined

解構賦值還可使用默認值,這樣就避免了不存在的屬性返回undefined的問題:

var {name, single=true} = person;
name; // '小明'
single; // true

當變量已經聲明後再進行解構賦值時要注意,應該使用小括號括起來,不然花括號會被當作塊處理而引起錯誤。

var x, y;
{x, y} = {name: '小明', x: 100, y: 200}; // 引起語法錯誤: Uncaught SyntaxError: Unexpected token =
({x, y} = {name: '小明', x: 100, y: 200}); // 正確

使用場景

解構賦值在不少時候能夠簡化代碼。例如,交換兩個變量x和y的值,能夠這麼寫, 再也不須要臨時變量:

var x=1, y=2;
[x, y] = [y, x];

快速獲取當前頁面的域名和路徑:

var {hostname: domain, pathname: path} = location;

若是一個函數接收一個對象做爲參數,那麼,可使用解構直接把對象的屬性綁定到變量中。例如:

function buildDate({year, month, day, hour=0, minute=0, second=0}) {
    return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}

buildDate({year: 2017, month: 1, day: 1});

1八、方法

在對象中綁定的函數,被稱爲這個對象的方法。

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function() {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
};

xiaoming.age;  // [Function: age] 這樣不會調用要加上小括號
xiaoming.age(); // 根據調用時的日期計算當前年齡

方法和普通函數沒有太多區別。

this 關鍵字

在一個方法內部,this是一個特殊變量,它始終指向當前對象,也就是xiaoming這個變量。因此,可使用tihs獲取當前對象的屬性,或者調用方法。
可是,當方法函數放在對象外部,或者是嵌套在方法函數中時,this根據調用狀況會有所不一樣。看下面示例:

function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};

xiaoming.age(); // 得到正常結果
getAge(); // NaN, 此時,this指向window對象,window此時沒有birth屬性、
var fn = xiaoming.age();
fn(); // NaN,只有用「對象.方法()」調用時,this纔會指向正確的對象

注意,ES5以後在strict模式下,函數中的this不在指向window而是指向undefined。此時,直接調用使用了this的函數時,會引起TypeError: this is undefined 錯誤。當方法中嵌套的函數中要使用對象的屬性時,應該用一個that變量先捕獲this,而後再在嵌套函數中使用that變量:

'use strict';

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var that = this; // 在方法內部一開始就捕獲this
        function getAgeFromBirth() {
            var y = new Date().getFullYear();
            return y - that.birth;
        }
        return getAgeFromBirth();
    }
};

xiaoming.age() // 28

apply方法

函數的apply方法可使函數中的this綁定到指定的對象。

function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}

var xiaoming = {
    name: '小明',
    birth: 1990,
};

getAge.apply(xiaoming, []); // 28, this 指向xiaoming,  參數爲空

另外一個與apply()相似的方法是call(),區別是:
apply()把參數打包成數組再傳入;
call()把參數按順序傳入。

好比調用Math.max(3, 5, 4), 分別用apply() 和 call() 實現以下:

Math.max.apply(null, [3, 5, 4]); //5
Math.max.call(null, 3, 5, 4); // 5

對於普通函數調用,咱們一般把this綁定爲null。

裝飾器

利用apply(),咱們還能夠動態改變函數的行爲。
JavaScript 的全部對象都是動態的,即便內置的函數,咱們也能夠從新指向新的函數。

例如:假定咱們要統計一下代碼一共調用了多少次parseInt()函數。

'use strict';

var count = 0;
var oldParseInt = parseInt; // 保存原函數

window.parseInt = function() {
    count +=1;
    return oldParseInt.apply(null, arguments); // 調用原函數
};

parseInt('10');
parseInt('20');
parseInt('30');
console.log('count = ' + count); //3

1九、高階函數(Higher-order function)

JavaScript的函數其實都綁定到某個變量。既然變量能夠指向函數,函數的參數能接收變量,那麼一個函數就能夠接收另外一個函數做爲參數,這種函數就稱之爲高階函數。

一個最簡單的高階函數:

function add(x, y, f) {
    return f(x) + f(y);
}

當咱們調用add(-5, 6, Math.abs)時,參數x, y 和f分別接收-5, 6 和函數Math.abs,根據函數定義,咱們能夠推導計算過程爲:

x = -5;
y = 6;
f = Math.abs;
f(x) + f(y) ==> Math.abs(-5) + Math.abs(6) ==> 11;
return 11;

map/reduce

map用於對數組的每個元素進行處理

舉例,好比咱們有一個函數f(x) = x^2,要把這個函數做用在一個數組[1, 2, 3, 4, 5, 6, 7, 8, 9] 上, 就能夠用map實現以下:

'use strict';

function pow(x) {
    return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow);
console.log(results); // [1, 4, 9, 16, 25, 36, 49, 64, 81]

reduce

reduce接收一個函數做爲參數,函數有兩個參數,效果以下:


function f(x,y){
    ......
}
[x1, x2, x3, x4 ,x5].reduce(f) = f(f(f(f(x1,x2),x3),x4),x5);

filter

用於把數組中的某些元素過濾掉,而後返回剩下的元素。
和map()相似,filter()也接收一個函數。filter()把傳入的函數一次做用於每一個元素,而後根據返回值是true仍是false決定保留仍是丟棄改元素。
例如,在一個數組中刪除掉偶數,只保留奇數,能夠這樣寫:

var arr = [1, 2, 3, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function(x){
    return x % 2 !== 0;
});
r; // [1, 5, 9, 15]

把一個數組中的空字符串刪掉, 能夠這麼寫:

var arr = ['A', '', 'B', null, undefined, 'C', '  '];
var r = arr.filter(function(s) {
    return s && s.trim(); //注意,IE9如下的版本沒有trim()方法
});
r; // ['A', 'B', 'C']

回調函數

filter() 接收的回調函數,其實能夠有多個參數。一般咱們僅適用第一個參數,表示數組的某個元素。
回調函數漢能夠接收另外兩個參數,表示元素的位置和數組自己:

//去掉重複元素
var arr = ['A', 'B', 'C', 'A', 'D', 'C', 'E'];
var r = arr.filter(function (element, index, self) {
    return self.indexOf(element) === index; //查詢當前元素位置,若是位置和當前位置相等則表示非重複元素
});

sort排序

數組的sort()方法排序,可能會獲得意想不到的結果:

['Goolge', 'Apple', 'Microsoft'].sort(); // ['Apple', 'Google', 'Microsoft']
['Google', 'apple', 'Microsoft'].sort(); // ['Google', 'Microsoft', 'apple']
[10, 20, 1, 2].sort();  // [1, 10, 2, 20]

能夠看出,字符串時按ASCII順序進行排序的,而數字排序也都先轉換成字符串後再進行排序。

sort也是高階函數,因此咱們能夠傳遞一個比較函數來實現自定義的排序。
例如,按數字大小排序:

'use strict';

var  arr = [10, 20, 1, 2];
arr.sort(function(x, y) {
    if (x < y) {
        return -1; //小於返回-1
    }
    if (x > y) {
        return 1; //大於返回1
    }
    return 0; // 等於返回0
});
console.log(arr); // [1, 2, 10, 20]

注意,sort()方法會直接對調用的數組進行修改,它返回結果仍然是當前數組。

20、閉包

函數做爲返回值

相關文章
相關標籤/搜索