obj = {f:function(){return this === obj}};
(a = obj.f)(); //return false
一个赋值表达式操作的本身也是有结果的, 它是右边操作数的值, 注意, 这里是值, 而不是引用, 下面测试中a将是一个函数而不是一个带着this
对象信息的方法。
声明是在语法分析阶段就处理的, 并且因此它会使得当前代码上下文在正式执行前就拥有了被声明的标识符
console,log(x); //undefined
var x = 1000;
console.log(x);
它们都是在读取一个已经存在的"标识符"名,
var y = "outer";
function f() {
console.log(y); //undefined
console.log(x); //error
let x = 100;
var y = 100;
}
JavaScript 是允许访问还没有绑定值的var所声明的标识符的。这种标识符后来统一约定称为“变量声明(varDelcs)”,而“let/const”则称为“词法声明“(lexicalDecls)”
javaScript在为环境创建一个变量名后, 会为它初始化绑定一个undefined值, 而词法名字在创建之后就没有这项待遇
赋值操作:
lRef = rValue
当向一个不存在的变量赋值的时候,由于全局对象的属性表是可以动态添加的,因此JavaScript 将变量名作为属性名添加给全局对象。而访问所谓全局变量时,就是访问这个全局对象的属性。因此,实际效果就变成了“可以动态地向全局环境中添加一个变量”。并且,显然地,我们在第一讲已经讲过这个结果——你可以删除掉这个动态添加的“变量”,因为本质上就是在删除全局对象的属性
为了兼容旧的 JavaScript 语言设计,现在的 JavaScript 环境仍然是通过将全局对象初始化为这样的一个全局闭包来实现的。但是为了得到一个“尽可能”与其它变量环境相似的声明varDecls,ECMAScript 规定在这个全局对象之外再维护一个变量名列表(varNames),所有在静态语法分析期或在 eval() 中使用var声明的变量名就被放在这个列表中。然后约定,这个变量名列表中的变量是“直接声明的变量”,不能使用delete删除。
所以,表面看起来“泄漏到全局的变量”与使用var声明的都是全局变量,并且都实现为global 的属性,但事实上它们是不同的。并且当var声明发生在 eval() 中的时候,这一特性又还有所不同,例如:
eval('var a = 1')
Object.getOwnPropertyDescriptor(global, 'a').configurable;
delete a;
//true
a;
ref error
现在回到今天讨论的这行代码var x = y = 100,在这行代码中,等号的右边是一个表达式y = 100,它发生了一次“向不存在的变量赋值”,所以它隐式地声明了一个全局变量y,并赋值为 100。