hoisting
console.log(a)
var a = 10
會變成類似(會說是類似,因為底層不一定是這樣做)
var a
console.log(a)
a = 10
可以把他
var a = '1'
// A...
var b = 2
// B ...
var c
想像成這樣
function whatever(a,b,c) {
// A ...
// B ...
}('1',1,undefined);
如果有let
var a = '1'
function x() {
// a ...
let a = 2
}
先想像成
function whatever(a) {
function x() {
// a ...
let a = 2
// b ...
}
}('1')
再想像成let會把前面提到同樣變數砍掉,在let的地方展開成function apply
var a = '1'
function whatever() {
function x() {
// a ...
function whatever2(a) {
// b ...
}(2)
}
}('1')
在Scheme怎麼處理mutual recursion?
據說當初JS有hoisting是為了方便寫mutual recursion。 先不說mutual recursion平常很少用到,先來看看scheme(或ML家族語言)是如何處理mutual recursion
有一個東西叫letrec
(letrec
[(even? (lambda (x)
(if (zero? x)
#t
(odd? (- x 1)))))
(odd? (lambda (x)
(if (zero? x)
#f
(even? (- x 1)))))]
even?)
在這個範圍都是可以互相參照的,個人比較偏好這種方式啦
例子
(function() {
var a = b = 5;
})();
console.log(b);
b會是global!! 所以印出5
同理
for (var i=0;i<10;i++)
console.log(i)
console.log(i)
最後會是10
還有function也會hoisting
function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test()
會印 undefined 2
Ref
builtin type
- string 是 Immutable
- 字面常數是value type
- new的是reference type
- 字面常數與new出來的不同
- 字面常數不能加method上去
var s = 'abc';
var s2 = s.slice(); // 'abc' (a clone)
s == s2 // true
var s3 = new String(s); // object
var s4 = new String(s); // object
s3 == s4 // false
// 用 === 從可怕的隱式轉換拯救自己
undefined就是undefined(c的void)
null是object
falsy value
- false
- 0
- ''
- null
- undefined
- NaN
'' == '0' // false
'' == 0 // true
'0' == 0 // true
' \t\r\n' == 0 // true
false == 'false' // false
false == 0 // true
false == undefined // false
false == null // false
null == undefined // true
NaN == NaN // false
event bubbling
從樹根往下走,走到終點,只有終點的事件,會執行冒泡與捕獲的事件,其他都是看在什麼階段就執行什麼階段的事件。
如果是終點有設定冒泡與捕獲的事件,那事件的執行順序,就看當初加入事件的順序
斬斷鎖鏈
e.stopPropagation (單體攻擊)
// list 的捕獲
$list.addEventListener('click', (e) => {
console.log('list capturing');
e.stopPropagation(); // <--- 這邊這事件就不會繼續下去
}, true)
// list 的捕獲 2
$list.addEventListener('click', (e) => {
console.log('list capturing2'); // <--- 這邊 會 繼續下去
}, true)
e.stopImmediatePropagation (AOE)
// list 的捕獲
$list.addEventListener('click', (e) => {
console.log('list capturing');
e.stopImmediatePropagation(); // <--- 會讓同一層的所有事件停止
}, true)
// list 的捕獲 2
$list.addEventListener('click', (e) => {
console.log('list capturing2');
}, true)
e.preventDefault (AOE ver.針對browser)
// list_item_link 的冒泡
$list_item_link.addEventListener('click', (e) => {
e.preventDefault();
}, false)
當點超連結的時候,就不會執行原本預設的行為(新開分頁或是跳轉),而是沒有任何事情發生。
prototype & interface
function newObj(Constructor, arguments) {
var o = new Object();
// 讓 o 繼承原型鍊
o.__proto__ = Constructor.prototype;
// 執行建構函式
Constructor.apply(o, arguments);
// 回傳建立好的物件
return o;
}
可以想像成Constructor.prototype
是class變數與方法的env
__proto__
就是parent的指標
用apply完成填值的動作
另外,apply與call都是差不多的東西,只是一個是放參數列,一個是給array bind就是會先綁定this成某個Object,只後丟出function