六種基本數據類型:數字Number、字符串String、未定義Undefined、空Null、布爾值Boolean、Symbol(ES6)node
三種引用類型:對象Object、數組Array、函數Functiones6
有幾點須要注意的:編程
==和===:使用==時,會自動轉換符號兩邊的數據類型再進行比較,容易出錯。使用===時,不會自動轉換數據類型,因此也對數據類型進行了比較。數組
null和undefined:null表示沒有這個值,而undefined表示應該有這個值但沒有定義。瀏覽器
undefined == null //true undefined === null //false
NaN和Infinite:NaN表示不是一個數值,它不與任何值相等,Infinite表示超出了Number類型能表示的最大範圍服務器
typeof和instanceof:typeof能夠把數據類型做爲字符串返回,但對於array、null和對象,typeof一概返回object。instanceof用於判斷一個變量是不是某個對象的實例。網絡
在 JavaScript 中, 對象和函數一樣也是變量,做用域爲可訪問變量,對象,函數的集合。閉包
局部變量和局部做用域:app
變量在函數內聲明,爲局部變量,局部做用域只能在函數內部訪問。(函數參數只在函數內起做用,是局部變量)編程語言
全局變量和全局做用域:
變量在函數外定義,即爲全局變量。全局變量有全局做用域, 網頁中全部腳本和函數都可使用。
變量生命週期:
JavaScript 變量生命週期在它聲明時初始化。局部變量在函數執行完畢後銷燬。全局變量在頁面關閉後銷燬。
注意:在 HTML 中, 全局變量是 window 對象: 全部數據變量都屬於 window 對象。
做用域的好處是內部函數能夠訪問定義它們的外部函數的參數和變量(除了this和arguements),不可逆。
變量聲明時若是不使用 var 關鍵字,那麼它就是一個全局變量,即使它在函數內定義。
出於種種緣由,咱們有時候須要獲得函數內的局部變量。可是,正常狀況下,這是辦不到的,只有經過變通方法才能實現。那就是在函數的內部,再定義一個函數。
function f1(){ var n=999; function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999
在上述代碼中,f2其實就是閉包。本質上,閉包就是可以讀取其餘函數內部變量的函數。
調用一個函數將暫停當前函數的執行,傳遞控制權和參數給新函數,除了聲明時定義的形式參數,每一個函數接收兩個附加的參數:this和arguements。參數this在面向對象編程中很是重要,它的取值取決於調用的模式,在JavaScript中一共有四種調用模式:方法調用模式、函數調用模式、構造器調用模式和apply調用模式。
當一個函數被保存爲一個對象的屬性時,咱們稱它爲一個方法。
方法可使用this去訪問對象。
var myObject={ value:0; increment:function(inc){ this.value+=typeof inc==='number'?inc:1; } }; myObject.increment(); document.writeln(myObject.value);
當一個函數並不是一個對象的屬性時,那麼它被看成一個函數來調用。當函數以此模式調用時,this被綁定到全局對象。
當內部函數被調用時,this應該仍然綁定到外部函數的this變量,因此咱們給該方法定義一個變量並給它賦值爲this,那麼內部函數就能夠經過那個變量訪問到this,不過ES6中箭頭函數的出現,有效的解決了this的指向問題。
JavaScript是一門基於原型繼承的語言,這意味着對象能夠直接從其餘對象繼承屬性,這偏離了當今編程語言的主流,當今大多數語言都是基於類的語言,儘管原型繼承有着強大的表現力,但它並不被普遍理解,因此JavaScript提供了一套和基於類的語言相似的對象構建語法。(ES6中新增了類,實質就是原型的語法糖)
構造函數中 this 關鍵字沒有任何的值。this 的值在函數調用實例化對象(new object)時建立。
// 構造函數: function myFunction(arg1, arg2) { this.firstName = arg1; this.lastName = arg2; } // This creates a new object var x = new myFunction("John","Doe"); x.firstName; // 返回 "John"
由於JavaScript是一門函數式的面向對象編程語言,因此函數能夠擁有方法。
call() 和 apply() 是預約義的函數方法,經過 這兩個方法你能夠設置 this 的值, 且做爲已存在對象的新方法調用。 兩個方法可用於調用函數,兩個方法的第一個參數必須是對象自己
function myFunction(a, b) { return a * b; } myObject = myFunction.call(myObject, 10, 2); // 返回 20
function myFunction(a, b) { return a * b; } myArray = [10, 2]; myObject = myFunction.apply(myObject, myArray); // 返回 20
兩個方法都使用了對象自己做爲第一個參數。 二者的區別在於第二個參數: apply傳入的是一個參數數組,也就是將多個參數組合成爲一個數組傳入,而call則做爲call的參數傳入(從第二個參數開始)。
在 JavaScript 嚴格模式(strict mode)下, 在調用函數時第一個參數會成爲 this 的值, 即便該參數不是一個對象。
在 JavaScript 非嚴格模式(non-strict mode)下, 若是第一個參數的值是 null 或 undefined, 它將使用全局對象替代。
高階函數源自於函數式編程,是函數式編程的基本技術。函數能夠做爲參數傳遞,也能夠做爲返回值返回。
這裏還有篇蠻詳細的文章,戳我~
四種規範:
AMD (require.js)
CMD (sea.js)
CommonJS (node.js)
ES6 模塊 (原生JS)
由於AMD和CMD規範已經逐漸被淘汰,因此咱們只來學習CommonJS和ES6模塊。
Node.js是commonJS規範的主要實踐者,它有四個重要的環境變量爲模塊化的實現提供支持:module、exports、require、global。
實際使用時,用module.exports定義當前模塊對外輸出的接口(不推薦直接用exports),用require加載模塊。
CommonJS 規範加載模塊是同步的,也就是說,只有加載完成,才能執行後面的操做。這是由於服務器中模塊都在磁盤中,讀取很是快。可是,若是是瀏覽器環境,要從服務器端加載模塊,這時就必須採用非同步模式(由於網絡緣由),所以瀏覽器端通常採用 AMD 規範或者ES6加載。
模塊功能主要由兩個命令構成:export和import,export命令用於規定模塊的對外接口,import命令用於輸入其餘模塊提供的功能。
export default命令,爲模塊指定默認輸出)
// 寫法一 export var m = 1; // 寫法二 var m = 1; export {m}; // 寫法三 var n = 1; export {n as m};
// 報錯 export 1; // 報錯 var m = 1; export m;
若是想爲輸入的變量從新取一個名字,import
命令要使用as
關鍵字,將輸入的變量重命名。
import { lastName as surname } from './profile.js';
import
命令輸入的變量都是隻讀的,由於它的本質是輸入接口。也就是說,不容許在加載模塊的腳本里面,改寫接口。
import
後面的from
指定模塊文件的位置,能夠是相對路徑,也能夠是絕對路徑,.js
後綴能夠省略。若是隻是模塊名,不帶有路徑,那麼必須有配置文件,告訴 JavaScript 引擎該模塊的位置。
ES6模塊詳細見這裏
二者差別見這裏