六大類型
Undefined
Null
Bollean
String
Number
Object
對象類型
原生對象:
- 構(gòu)造函數(shù):Boolean, String, Number, Object, Function, Array, Date, RegExp, Error
- 對象: Math, JSON
宿主對象: window, navigator, document
瀏覽器擴(kuò)展對象: - ActiveXObject, XML, Debug, Script, VBArray
- 逐漸被棄用
隱式類型轉(zhuǎn)換:
- Undefined轉(zhuǎn)為Number為NAN
- 空字符串轉(zhuǎn)為Boolean為false
- 所有的對象轉(zhuǎn)為Boolean都是true
類型識別:
- typeof:
- 判斷基礎(chǔ)類型,返回的是字符串
- 如果是對象則返回'object'恶耽。
- typeof null === 'object'
- typeof Function === 'function'
- instanceof
- 判斷對象類型,可判斷子類
- 不能判別原始類型:1 instanceof Number === false
- Object.prototype.toString.call
- 可以識別標(biāo)準(zhǔn)類型和內(nèi)置對象類型
- 不能識別自定義對象類型
- Object.prototype.toString.call(123) === 'Number'
- constructor
- 可以判別準(zhǔn)備類型、內(nèi)置對象類型、自定義對象類型
- 不能判別null,Undefined
- (1).constructor === Number
function getConstructorName(obj){
return ( obj === undefined || obj === null )? obj+'' : obj.constructor.toString().match(/function\s*([^(]*)/)[1];
}
- getConstructorName(null) --> null
- getConstructorName(new Date()) --> 'Date'
函數(shù)
//函數(shù)聲明
function foo(){}
//函數(shù)表達(dá)式
var foo = function(){};
//函數(shù)實例化
var foo = new Function('i','console.log(1);');
//變量沾凄、函數(shù)聲明前置:
//function
console.log(foo);
//undefined
console.log(bar);
function foo(){}
var bar = function(){};
js作用域:對象题篷、函數(shù)有獨立作用域
函數(shù)調(diào)用方式
Function.prototype.apply(this, [])
Function.prototype.call(this, ...args)
//保存函數(shù)的參數(shù),以便直接調(diào)用
var fooCopy = foo.bind(this, ..args);
fooCopy();
arguments
arguments是一個Array-like對象
閉包
- 相當(dāng)于一個對象佛掖,內(nèi)部可以維護(hù)成員變量和成員函數(shù)
原型vs類
- 類是抽象概念,java中用類構(gòu)造對象涌庭。
- 原型是一個對象(Function)苦囱,js中用對象(Function)構(gòu)造對象。
設(shè)置對象的原型
- Object.create(proto);
- 傳入一個原型脾猛,返回一個對象
var Car = {
start: function(){
console.log('start');
}
}
var landRover = Object.create(Car);
//'start'
landRover.start();
- 使用構(gòu)造函數(shù)構(gòu)造對象撕彤,使用prototype設(shè)置原型
var Car = function(){
}
Car.prototype.start = function(){
console.log('start');
}
var landRover = new Car();
//'start'
landRover.start();
原型鏈繼承
//Car構(gòu)造函數(shù)
var Car = function(){
}
Car.prototype.start = function(){
console.log('start');
}
//LandRover構(gòu)造函數(shù)
var LandRover = function(){
}
LandRover.prototype = new Car();
var landRover = new LandRover();
//start
landRover.start();
obj.hasOwnProperty(name);
- 對象自身是否有該屬性
構(gòu)造函數(shù)的原型鏈
Car --> Function --> Object
LandRover --> Function --> Object
- 因為Car和LandRover都是函數(shù)(Function)的實例,所以可以訪問Function的原型方法猛拴,即Function.prototype的方法羹铅,即Car.proto = Function.prototype
- Function是Object的實例,所以可以訪問對象的原型方法愉昆,即Object.prototype的方法
JS變量作用域
- JS使用靜態(tài)作用域
var x = 10;
function foo(){
console.log(x);
}
function bar(){
var x = 20;
foo();
}
//10
bar();
- JS沒有塊級作用域职员,只有全局作用域和對象(函數(shù))作用域
- ES5中使用詞法環(huán)境管理靜態(tài)作用域(使用outer指向外層環(huán)境,內(nèi)層函數(shù)可以訪問外層變量)
- with關(guān)鍵字可以創(chuàng)建臨時環(huán)境
var obj = {foo:'bar'};
with(obj){
//'bar'
console.log(foo);
}
聲明函數(shù)與函數(shù)表達(dá)式
- 聲明函數(shù)會被提前定義跛溉,他的作用域為靜態(tài)作用域焊切,outer指向全局環(huán)境。
- 函數(shù)表達(dá)式在執(zhí)行的時候才會被創(chuàng)建芳室,他的作用域為動態(tài)作用域专肪,outer指向當(dāng)前環(huán)境。
帶名稱的函數(shù)表達(dá)式
- 執(zhí)行該表達(dá)式的時候堪侯,會動態(tài)創(chuàng)建一個作用域嚎尤,使得在函數(shù)內(nèi)可以使用A來訪問該函數(shù)。
- 在函數(shù)外并不能訪問到A
(function foo(){
//foo并沒有被修改
foo = 1;
//function
console.log(foo);
})();
//error
console.log(foo);
使用函數(shù)表達(dá)式創(chuàng)建閉包
- 利用函數(shù)表達(dá)式的作用域特性伍宦,可以創(chuàng)建閉包(內(nèi)部函數(shù)訪問外部函數(shù)的變量)芽死。
function foo(){
var i = 0;
return function(){
console.log(i++);
}
}
var bar = foo();
//0
bar();
//1
bar();
閉包的應(yīng)用
- 保存現(xiàn)場(變量的值乏梁、狀態(tài)等)
//錯誤實例
function addHandlers(nodes){
for(var i=0; i<nodes.length;i++){
nodes[i].onclick = function(){
//當(dāng)函數(shù)執(zhí)行的時候,i已經(jīng)變成了nodes.length关贵,所以所有的node都會打印nodes.length
console.log(i);
}
}
}
//使用閉包
function addHandlers(nodes){
//每調(diào)用一次helper遇骑,都會創(chuàng)建一個閉包,保存i的值
function helper(i){
return function(){
//0 1 2 3
console.log(i);
};
}
for(var i=0;i<nodes.length;i++){
nodes[i].onclick = helper(i);
}
}
- 封裝(信息隱藏揖曾,提供接口)