词法做用域就是定义在词法阶段的做用域。简单说,词法做用域是由你在写代码时将变量和块做用域写在哪里来决定的,所以当词法分析器处理代码时会保持做用域不变(大部分状况下)。浏览器
// 全局做用域,只有一个标识符:foo
function foo(a){
// foo所建立的做用域,三个标识符:b,a,bar
var b = a * 2;
function bar(c){
// bar所建立的做用域,只有一个标识符:c
console.log(a,b,c);
}
bar(b * 3);
}
foo(2); // 2,4,12
复制代码
做用域气泡由其对应的做用域代码写在哪里决定,它们是逐级包含的。 没有任何函数能够部分地同时出如今两个父级函数中。bash
做用域气泡的结构和相互之间的位置关系给引擎提供了足够的位置信息,引擎用这些信息来查找标识符的位置。函数
做用域查找会在找到第一个匹配的标识符时中止。在多层的嵌套做用域中能够定义同名的标识符,产生“遮蔽效应”。性能
全局变量会自动成为全局对象(好比浏览器中的window对象)的属性,所以能够经过window.a的方式进行访问那些被同名变量所遮蔽的全局变量。但非全局变量被遮蔽的时候是没办法访问到的 学习
不管函数在哪里被调用,也不管它如何被调用,它的词法做用域都只由函数被声明时所处的位置决定。优化
欺骗词法做用域会致使性能降低。ui
JavaScript中的eval()函数能够接受一个字符串为参数,能够在你写的代码中用程序生成代码并运行,就好像代码是写在那个位置的同样。spa
eval()进行欺骗词法的原理就是:在运行期修改书写期的词法做用域code
function foo(str,a){
eval(str); // 欺骗
console.log(a,b);
}
var b = 2;
foo("var b = 3",1); // 1,3
复制代码
在严格模式下,eval()在运行时有本身的词法做用域
function foo(str){
"use strict";
eval(str);
console.log(a); // ReferenceError:a is not defined
}
foo("var a = 2");
复制代码
setTimeout()和setInterval()也能够实现跟eval()同样的效果。对象
with一般被看成重复引用同一个对象中的多个属性的快捷方式,能够不须要重复引用对象,例如:
var obj = {
a: 1,
b: 2,
c: 3
}
// 改值
obj.a = 2;
obj.b = 3;
obj.c = 4;
// with改值
with(obj){
a = 3;
b = 4;
c = 5;
}
复制代码
考虑以下代码:
function foo(obj){
with(obj){
a = 2;
}
}
var o1 = {
a: 3
}
var o2 = {
b: 3
}
foo(o1);
console.log(o1.a); // 2
foo(o2);
console.log(o2.a); // undefined
console.log(a); // 2 -- a 被泄露到全局做用域
复制代码
with块能够将一个对象处理为词法做用域,可是这个块内部正常的var声明并不会被限制在这个块做用域中,而是被添加到with所处的函数做用域中。
1.词法做用域意味着做用域是由书写代码时函数声明的位置决定的。编译的词法分析阶段基本可以知道所有标识符在哪里以及是如何声明的,从而可以预测在执行的过程当中如何对它们进行查找。
2.JavaScript“欺骗”词法做用域的两个机制:eval()和with,反作用是引擎没法在编译时对做用域查找进行优化,致使代码运行变慢,不建议使用。
工做是什么?
以一个俗人的角度多是为了生存,衣食住行,以一个超脱的人的角度多是实现自个人价值,获得某种荣耀或者升华,对目前的我来讲,工做是什么,只是工做,这样说有点偷换概念,明明没有回答什么,工做如今是个人生活的一部分,有时候我会由于它开心,有时候会由于它难过,但愿本身能作到一个日常心,就像常常被灌输的只是进城打工,看淡,认真,不较真,与人为善,技术上多学习,多思考,多总结。