作用域
- JS中并没有块作用域, 只有函数作用域
- 作用域, 指的是, 变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的
全局变量
- 不使用 var保留字声明变量, 变量提升为全局变量, 不论变量处于哪种作用域,会直接挂载在 window上
- 如果不使用var声明, 该变量便可配置, 即可被 delete 保留字删除, 删除后该变量便不可访问;
- 如果使用var声明, 该变量便不可配置, 即不能被 delete 保留字删除;
- 只要是全局变量都可以直接访问, 也可使用 “window.变量名” 来访问, 不管该变量是不是通过var来声明的
作用域链
- 函数的作用域链,决定了哪些数据能被函数访问
- 函数的执行环境(excution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)
闭包
- 由于闭包可能会使得函数中变量被长期保存在内存中, 从而大量消耗内存, 影响页面性能, 因此不能滥用
- 解决方法是,在退出函数之前,将不使用的局部变量全部删除
var div = document.getElementsByTagName("div");
for(var i=0,len=div.length;i<len;i++){
(function(n){
div[n].onclick = function(){
console.log(n);
}
})(i);
}
- 由于 click 事件被闭包包裹, 并且闭包自执行,因此闭包内 n 变量的值每次都不一样
- 点击div时, 浏览器将沿着 scope chain 寻找 n 变量,
- 最终会找到闭包内的 n 变量, 并且打印出div 的索引
匿名函数
- 使用匿名函数后, 不止是作用域查询更快, 作用域内的变量还与外部隔离
- 避免了像 i , length 这样的变量对后续代码产生影响
(function(){// 闭包
for(var i=0,length = array.length; i<length;i++){
console.log(i)
}
})();
this
当f单独执行时, 其内部this指向window对象, 但是当f成为o对象的属性func时, this指向的是o对象, 又f === window.f
, 故它们实际上指向的都是this所在方法的对象
with
- with语句可以用来临时改变作用域, 将语句中的对象添加到作用域的顶部
with (expression){statement}
- with语句容易引起歧义, 由于需要强制改变作用域链, 它将带来更多的cpu消耗, 建议慎用 with 语句
var k = {name:"daicy"};
with(k){
console.log(name);//daicy
}
console.log(name);//undefined
- with 语句用于对象 k, 作用域第一层为 k 对象内部作用域, 故能直接打印出 name 的值,
- 在with之外的语句不受此影响