Open xccjk opened 2 years ago
JavaScript具有基于函数的作用域。函数内部标识符无论在函数何处,这个标识符所代表的变量或者函数都附属于当前函数所处的作用域
function foo(a) {
var b = 1;
var c = {};
function bar() {
// ...
}
}
console.log(a,b,c) // error
foo(...)的作用域中包含了标识符a、b、c、bar
由于标识符a,b,c,bar
都属于作用域foo
,因此无法从foo
的外部对它进行访问。
定义:函数作用域是指属于这个函数的全部变量都可以在整个函数的范围内使用
函数外部作用域无法访问包装函数内部的任何内容
var a = 2
function foo() {
var a = 3
console.log(a) // 3
}
foo()
console.log(a) // 2
// bad
function foo(a) {
b = a + bar(a * 2)
console.log(b * 3)
}
function bar(a) {
return a - 1
}
var b
foo(2) // 5
该方法不仅可以访问到foo
,还可以访问到变量b
和函数bar
// good
function foo(a) {
function bar(a) {
return a - 1
}
var b
b = a + bar(a * 2)
console.log(b)
}
foo(2) // 5
相比上面的方法,把变量b
和函数bar
变为了私有方法
function foo() {
function bar(a) {
i = 3
console.log(a + i)
}
for(var i = 0; i < 10; i++) {
bar(i * 2)
}
}
foo()
函数bar
内部变量i
覆盖了for
循环中的i
,导致了无限循环
区分函数声明和函数表达式,看function关键字出现在声明中的位置就可以判断。如果function是声明中的第一个词,就是一个函数声明,否则就是函数表达式
函数声明与函数表达式最重要的区别,就是它们的名称标识符会绑定在何处
函数声明
function foo() {
console.log('我是一个函数声明')
}
函数表达式
(function foo() {
console.log('我是一个函数表达式')
})()
匿名的函数表达式
(function () {
console.log('我是一个匿名的函数表达式')
})()
匿名函数表达式优缺点:
优点:
缺点:
arguments.callee
引用(function foo() {
})()
或者
(function () {
})()
或者
(function foo() {
}())
for(var i = 0; i < 5; i++) {
}
console.log(i) // 5
for
循环中,我们在头部定义了变量i
,希望在for
循环内部上下文中使用i
。实际情况下变量i
还可以在外部作用域访问到
存在的问题:for循环内部的变量i
可能会被外部变量i
赋值给更改掉
块作用域是一个用来对之前的最小授权原则进行扩展的工具,将代码从在函数中隐藏信息 扩展为在块中隐藏信息
with(true ) {}
try {
} catch(err) {
console.log(err)
}
console.log(err) // error
let 关键字可以将变量绑定到所在的任意作用域中
if (true) {
var a = 2
}
console.log(a) // 2
if (true) {
let b = 2
}
console.log(b) // b is not defined
使用 let 进行的声明不会在块作用域中进行提升
console.log(a) // undefined
var a = 1
console.log(a) // SyntaxError: Identifier 'a' has already been declared
let a = 1
var a = 1
a = 2
console.log(a) // 2
let a = 1
a = 2 // SyntaxError: Identifier 'a' has already been declared
for(var i = 0; i < 5; i++) {}
console.log(i) // 5
// 等价于
var i
for(i = 0; i < 5; i++) {}
console.log(i) // 5
for(let i = 0; i < 5; i++) {}
console.log(i) // ReferenceError: i is not defined
JavaScript事件委托
什么是事件委托?
利用JavaScript事件冒泡动态为元素绑定事件的方法称为事件委托。
事件委托就是把原本需要绑定在子元素上的事件委托到它的父元素,让父元素监听子元素的冒泡事件,并在子元素发生事件冒泡时找到这个子元素。
为什么需要事件委托
页面的事件个数会直接影响页面的整体性能,因为每个事件处理程序都是对象,对象会占用内存,内存中的对象越多,页面的性能越差
事件会频繁的操作DOM元素,DOM元素的操作会引起浏览器的重绘与重排
事件委托优点:
事件委托原理
事件委托是利用事件冒泡来实现的,流程:
不采用事件委托绑定事件:
采用事件委托绑定事件
[在线demo](https://codesandbox.io/s/javascriptshi-jian-wei-tuo-demo-j8lohp?file=/index.html:365-385)
总结