Author:
bugall
Wechat:bugallF
Email:769088641@qq.com
Github: https://github.com/bugalljavascript
空值(null) 未定義(undefined) 布爾值(boolean) 數字(number) 字符串(string) 對象(object) 符號(symbol,ES6新增)
typeof null === 'object' //true 正確的返回結果應該是"null",但這個bug由來已久, 在javascript中已經存在了將近20年,也許永遠也不會修復 由於這涉及太多現有的web系統,修復它會產生更多的bug
var a = null; (!a && typeof a === "object"); //true
實際上function是object的一個「子類型」, 函數是"可調用對象",它有一個內部屬性[[Call]], 該屬性使其能夠被調用
typeof [1,2,3] === "object"; //true
變量能夠隨時持有任何類型的值
變量在做用域中聲明可是沒有複製爲"undefined", 變量在做用域中未聲明"undeclared"
使用delete運算符能夠將單元從數組中刪除, 可是單元刪除後數組的length屬性並不會發生變化
var a = []; a[0] = 1; a[2] = 3; a[1]; //undefined a.length; //3
var a = []; a[0] = 1; a["bugall"] = 2; a.length; //1 a["bugall"] = 2; a.bugall = 2;
var a = []; a["13"] = 42; a.length; //14
javascript中的數字類型是基於IEEE 754標準實現的, 該標準一般也被稱爲「浮點數」,javascript使用的是 "雙精度"格式64位二進制
42..toFixed(2) = 42.00,42.toFixed(2) 是無效語法,由於.被視爲常量42.的一部分
二進制浮點數中0.1和0.2並非十分精確,它們相加的結果並不是恰好等於0.3,而是一個 很是接近的數字0.3000000000000000002
function numbersCloseEnoughToEqual(n1,n2){ return Math.abs(n1-n2)<Number.EPSILON } numbersCloseEnoughToEqual(0.3,0.3) //true
數字的呈現方式決定了「整數」的安全值範圍遠遠小於 Number.MAX_VALUE,最大是2^53-1
Number.isInterger(42) //true Number.isInterger(42.000) //true Number.isInterger(42.001) //false
undefined類型只有一個值,即undefined, null類型也只有一個值,即null,它們的名稱是類型也是值
若是數學運算的操做不是數字類型,就沒法返回一 個有效的數字,這種狀況下返回值爲NaN
var a = 2 / "foo" //NaN typeof a === "number" //true
NaN是執行數學運算沒有成功返回的結果, NaN是一個特殊值,它和自身不相等,是惟一一個非自反的值 NaN != NaN //true
前者一直是我錯誤的理解,正確的理解應該是is NaN, 判斷數學運算是否錯誤,返回錯誤的值
var a = 2 / "foo" var b = "foo" a; //NaN b; //"foo" isNaN(a) //true isNaN(b) //true 這是不一樣的結果,一個是運算出錯,一個是字符串
代碼中儘量得少出現isNaN()
null,undefined,string,number,boolean
咱們沒法更改使用值傳遞仍是引用傳遞,一切根據值的類型肯定
function a(){...} //函數聲明 var a = function(){...} //函數表達式
(function foo(){ var a=3; console.log(a) //3 })() 因爲函數被包含在一對()括號內部,所以成爲一個函數表達式, 經過在末尾加上另外一個()能夠當即執行這個函數。 第一個()將函數變成表達式
console.log(a) //undefined var a = 3; console.log(a) //3
console.log(a) //undefined if(false){ var a = 3; }
{ console.log(a) //ReferenceError var a = 3 console.log(a) //3 }
foo() //bugall function foo(){ console.log('bugall') } a() // ReferenceError var a = foo(){ console.log('bugall') }
function a(){ var n = 'bugall' function b(){ console.log(n) } return b } foo() //'bugall' 覺得b()覆蓋了a()裏的變量n,因此a的資源就沒法釋放,而這個引用就叫作閉包
var obj = { name = 'bugall', sayName = function(){ console.log(this.name) }) } var name = 'not bugall' obj.cool() //bugall ,this的做用域是obj對象 setTimeount(obj.cool,100) //not bugall,this變成了當前做用域 用this的形式 var obj = { name = 'bugall', sayName = function(()=>{ console.log(this.name) }) } var name = 'not bugall' obj.cool() //bugall ,this的詞法做用域是obj setTimeount(obj.cool,100) //bugall, this的詞法做用域沒有變
function foo(){ foo.count = 4; //foo指向自身 } setTimeout(function(){ //匿名函數由於沒有名字,沒法指定在堆棧上得肯定位置,因此不能引用自身 })
function foo(){ console.log(this.a) } var a = 2 foo() //2
function foo(){ 'use strict' console.log(this.a) } var a = 2 foo() //TypeError: this is undefined
function foo(){ console.log(this.a) } var obj2 = { a:42, foo:foo } var obj1 = { a:2, obj2:obj2 } obj1.obj2.foo() //42
function foo(){ console.log(this.a) } var obj = { a:2 } foo.call(obj) //2 咱們在調用foo的時候強制把它的this綁定到obj上
function foo(something){ console.log(this.a,somethis) return this.a + something } var obj = { a:2 } var bar = foo.bind(obj) var b = bar(3) // 2 3 console.log(b) //5 bind(...)會返回一個硬編碼的新函數, 它會把你指定的參數設置爲this的上下文並調用原始函數
在javascript中,構造函數只是一些使用new操做符 時被調用的函數,他們並不會屬於某個類,也不會實例化一個類, 實際上它們甚至都不能說是一個特殊的函數類型,他們只是 被new操做符調用的普通函數而已。 使用new來調用函數的時候,會自動執行下面的操做 1. 建立(或者說構造)一個全新的對象 2. 這個新對象會被執行[[prototype]]鏈接 3. 這個新對象會被綁定到函數調用的this 4. 若是函數沒有返回其餘對象,那麼new表達式中的函數調用會自動返回這個新對象
function foo(a){ this.a=a } var bar = new foo(2) console.log(bar.a) //2
function foo(){ console.log(this.a) } var obj1 = { a:2, foo:foo } var obj2 = { a:3, foo:foo } obj1.foo() //2 obj2.foo() //3 obj1.foo.call(obj2) //3 obj2.foo.call(obj1) //2
function foo(somethis){ this.a = somethis } var obj1 = { foo:foo } var obj2 = {} obj1.foo(2) console.log(obj1.a)//2 obj1.foo.call(obj2,3) console.log(obj2.a) //3 var bar = new obj1.foo(4) console.log(obj1.a) //2 console.log(bar.a) //4 bar被綁定到obj1上,可是new bar(3)並無像咱們預期的那樣把obj1.a修改成3 相反,new修改了硬綁定(到obj1的)調用bar(...)中的this,由於使用了new綁定獲得 一個名字爲baz的新對象,而且baz.a的值是3
call,apply屬於顯示綁定 bind屬於硬綁定,硬綁定屬於顯示綁定的一種
硬綁定會下降函數的靈活性,使用硬綁定以後就 沒法使用隱式綁定或是顯式綁定來修改this
1. 函數是否在new中調用(new綁定),若是是的話this綁定的是新建立的對象 var bar = new foo() 2. 函數是否經過call,apply(顯示綁定)或者硬綁定調用, 若是是的話,this綁定的是指定的對象 var bar = foo.call(obj2) 3. 函數是否在某個上下文對象中調用(隱式綁定),若是是的話,this綁定的是那個上下文對象 var var = obj1.foo() 4. 若是都不是的話,使用默認綁定,若是在嚴格模式下,就綁定到undefined,不然綁定到全局對象 var bar = foo()