{}+[]与console.log({}+[])结果不同?从JavaScript的大括号谈起
看到这样一个问题:为什么直接在控制台运行{} + []和用console.log({} + [])输出,两者结果不一样?
于是乎打开chrome的控制台运行了一下:
为什么结果会这样呢?不得已学习一下JS中的{}吧
复合语句
1 if() { 2 //... 3 }else { 4 //... 5 } 6 for() { 7 //... 8 } 9 while() { 10 //... 11 } 12 with(obj) { 13 //... 14 }
声明对象直接量
1 var obj = { 2 name: 'Marco', 3 age: 22, 4 sex: male 5 };
声明函数或函数直接量
1 function fn1() { 2 //... 3 } 4 var fn2 = function() { 5 //... 6 }
没有块级作用域
1 for( var i = 0; i < 10; i++) { 2 doSomething(i); 3 } 4 5 alert(i); //10
javascript只有函数作用域,以下做法会声明全局变量:
- 直接为window添加属性或者赋值 //window.a = 1;
- 在function内不使用var声明变量而直接使用
- 在function外使用声明变量(无论是否适用var声明)
1 function(num1 , num2) { 2 var sum = num1 + num2; 3 return sum; 4 } 5 6 var result = add(10,20); //30 7 alert(sum); //错误 8 9 10 function(num1 , num2) { 11 sum = num1 + num2; 12 return sum; 13 } 14 15 var result = add(10,20); //30 16 alert(sum); //30
建议在初始化变量之前一定要先声明,这样可以避免不声明而直接初始化变量造成的错误。
当在某个环境中使用一个标识符时,必须先通过搜索来确定该标识符代表什么。搜索过程从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符。若在该环境中找到了该标识符,则搜索停止,变量就绪。若在该局部环境没有找到该变量,则继续沿作用域链向上搜索,一直追溯到全局环境的变量对象。若在全局环境中没有找到该标识符,则说明该变量尚未声明。
1 var num = 1; 2 3 function getNum() { 4 var num = 10; 5 return num; 6 } 7 8 alert(getNum()); //10
变量查询是有代价的。很明显,访问局部变量要比访问全局变量更快,因为不用向上搜索作用域链。来看看jquery这么做的:
(function(window, undefined) { var jQuery = function() {} // ... window.jQuery = window.$ = jQuery; })(window);
这样写的优势:
1、window和undefined都是为了减少变量查找所经过的scope作用域。当window通过传递给闭包内部之后,在闭包内部使用它的时候,可以把它当成一个局部变量,显然比原先在window scope下查找的时候要快一些。(原来的window处于作用域链的最顶端,查找速度慢)
2、在jquery压缩版本jquery.min.js中可以将局部变量window替换成单个字母,减小文件大小,提高加载速度。
3、undefined也是JavaScript中的全局属性。将undefined作为参数传递给闭包,因为没给它传递值,它的值就是undefined,这样闭包内部在使用它的时候就可以把它当做局部变量使用,从而提高查找速度。undefined并不是JavaScript的保留字或者关键字。
4、undefined在某些低版本的浏览器(例如IE8、IE7)中值是可以被修改的(在ECMAScript3中,undefined是可读/写的变量,可以给它赋任意值,这个错误在ECMAScript5中做了修正),将undefined作为参数并且不给它传值可以防止因undefined的值被修改而产生的错误。
结构化异常处理的语法符号
1 try { 2 //... 3 }catch( ex ){ 4 //... 5 }finally{ 6 //... 7 }
语句优先
当{}既可以被理解为复合语句块也可以被理解为对象直接量或函数声明的时候,JavaScript将会将其理解成为复合语句块
1 {a:10} //返回1,而不是对象 : 为标签 2 3 var x = { a:10 } // {a:10}作为右值出现,不能是语句块,只能理解为对象直接量
至此,{}的基本知识就说完了。那么最开始的问题也很好解释了:
{}+[] :根据语句优先原则 {}被理解为复合语句块,因此相当于 {}; +[] 。[]为空,结果为0
console.log({}+[]) : js把()中的语句当做一个表达式,因此{}不能被理解为语句块,而被理解为"[object Object]" + "",console.log("[object Object]"+"")打印结果为[object Object]。
其实 console.log({}+[])和[]+{}的结果相同,原理相同,{}作为右值出现被理解为对象直接量
{}+[] 和[]+{}结果不相同,是不是很神奇。
来来来,做几个练习题压压惊:
1 {a: 1} + 2 // 2 2 2 + {a: 1} // 2[object Object] 3 + {a: 1} // NaN 4 {foo:[1,2,3]}[0]; // [0]
以上