Javascript 容易忽视的语法点
2017-08-30 21:38
197 查看
使用 typeof bar === “object” 判断 bar 是不是一个对象有何潜在的弊端?如何避免这种弊端?
2.下面的代码会在 console 输出神马?为什么?
3.下面的代码会在 console 输出神马?为什么?
我们在sublime中写出来,实践出真知:
如果你知道闭包,下面的内容也是很好理解的:
4.将 JavaScript 代码包含在一个函数块中有什么意思呢?为什么要这么做?
这个问题其实就是看你是否掌握了闭包,关于闭包我打算专门写一篇博文,这个问题也可以理解为,IIFE的作用是什么
IIFE即是: 立即执行函数表达式(Immediately-Invoked Function Expression)
先看下下面这段代码:
5.下面两个函数的返回值是一样的吗?为什么?
6.神马是 NaN,它的类型是神马?怎么测试一个值是否等于 NaN?
var arr = []; var obj = {}; var nl = null; console.log(typeof arr === 'object'); //true console.log(typeof obj === 'object'); //true console.log(typeof nl === 'object'); //true // 从上面的输出结果可知, 使用 typeof 并不能准确判断 bar 就是一个 Object。 // 可以通过 Object.prototype.toString.call(bar) === "[object Object]" 来避免这种弊端: console.log(Object.prototype.toString.apply(arr)); //[object Array] console.log(Object.prototype.toString.apply(obj)); //[object Object] console.log(Object.prototype.toString.apply(nl)); // [object Null]
另外,在控制台检查会发现, if([]) { console.log('[] is true') } 点击Enter键 [] is true undefined []==true 点击Enter键 false []===true 点击Enter键 false []==false 点击Enter键 true ([]和 false值相同 ) []===false 点击Enter键 false ([]和 false类型不相同,===三个等号表示值和类型都相同) [object Array] VS [object Boolean]
2.下面的代码会在 console 输出神马?为什么?
(function(){ var a = b = 3; })(); console.log("a defined? " + (typeof a !== 'undefined')); console.log("b defined? " + (typeof b !== 'undefined'));
// 函数所创建的作用域中的局部变量,JS中只有函数可以创建作用。 // JS不存在块级作用域 // JS中是词法作用域(与之对立的为动态作用域),在代码写好的那一刻,作用域就已经确定了 // 词法作用域的规则: // 函数允许访问函数外的数据 // 如果当前作用域中有了该变量,就不考虑外面的同名变量 (function() { var a = b = 3; // 这一句等价于: // b = 3; 全局变量 // var a = b; })(); console.log(a); // Uncaught ReferenceError: a is not defined 报错后,后面的不执行,要想后面代码执行,需要屏蔽这一句。 console.log(typeof a); // undefined console.log(b); //3 console.log("a defined? " + (typeof a !== 'undefined')); //false console.log("b defined? " + (typeof b !== 'undefined')); // true
3.下面的代码会在 console 输出神马?为什么?
var myObject = { foo: "bar", func: function() { var self = this; console.log("outer func: this.foo = " + this.foo); console.log("outer func: self.foo = " + self.foo); (function() { console.log("inner func: this.foo = " + this.foo); console.log("inner func: self.foo = " + self.foo); }()); } }; myObject.func();
我们在sublime中写出来,实践出真知:
var myObject = { foo: "bar", func: function() { var self = this; //self指的是myObject对象 console.log(this); //这里的this指的是myObject对象 console.log("outer func: this.foo = " + this.foo); // bar !! console.log("outer func: self.foo = " + self.foo); // bar (function() { console.log(this);//这里的this指window console.log(self); //self就是myObject console.log("inner func: this.foo = " + this.foo); // undefined window上是没有foo属性的 console.log("inner func: self.foo = " + self.foo); // bar }()); } }; myObject.func(); 第一个和第二个的输出不难判断,self和this都是指的调用func的对象myObject,所以打印结果都是bar。 对于第三个,因为 this (指的是window)在可访问到的作用域内是 undefined,第四个输出是 undefined。 在 ES6 之前,JavaScript 只有函数作用域,所以 func 中的 IIFE 有自己的独立作用域,并且它能访问到外部作用域中的 self,所以第四个打印也是bar。
如果你知道闭包,下面的内容也是很好理解的:
var myObject = { foo: "bar", func: function() { var self = this; (function(test) { // 当myObject.func();执行完毕后,下面的IIFE等于放在最外层执行,此时的this指的是window console.log("inner func: this.foo = " + this.foo); //'bar' // 这里实参传递给形参等价于下面两行代码 // var test; // test = self; console.log(self); //self就是myObject console.log(test); //test就是self也即myObject console.log("inner func: this.foo = " + test.foo); //'bar' console.log("inner func: self.foo = " + self.foo); }(self)); } }; myObject.func();
4.将 JavaScript 代码包含在一个函数块中有什么意思呢?为什么要这么做?
这个问题其实就是看你是否掌握了闭包,关于闭包我打算专门写一篇博文,这个问题也可以理解为,IIFE的作用是什么
IIFE即是: 立即执行函数表达式(Immediately-Invoked Function Expression)
先看下下面这段代码:
for(var i =0;i<6;i++){ setTimeout(function(){ console.log(i); }, 1000); } 打印结果是什么呢? 六个6 很经典的一个问题: 所有的主任务的代码执行完毕之后,去检查所有的setTimeout回调函数,如果到时间了就执行,此时i已经变为6了。 可以用闭包来解决这个问题,关于闭包,我总结了三个关于闭包的特点,其实不用看我的总结,只要你观察下闭包,基本上也就是这三个特点: // 1.IIFE // 2.函数里面的内容不会立即执行,调用的时候(时间到了或者用户点击的时候)才会执行 // 3.1 函数里面内容虽然不会立即执行,如果再每次循环阶段(预解析阶段)把值以函数参数的形式传进去之后,在函数执行阶段,用的就是当时传进去的值 // 3.2 函数里面内容虽然不会立即执行,如果在内层作为返回值return出来的函数中,定义一个变量,引用了外层的变量,那么执行阶段,用的就是预解析阶段引用的值 好,我们看下钢材那个问题,如果想要输出0,1,2,3,4,5该怎么改写代码 for (var i = 0; i < 6; i++) { function foo(j) { return function() { /第2条 console.log(j); } } var f = foo(i); //第1条 第3.1条(至于第3.2条,等我专门写闭包了再讲吧) setTimeout(f, 1000); } 好了上面是IIFE的第一个常用之处。 ---------- 另外 JQuery/Node 的插件和模块开发中,为避免变量污染,也是一个大大的 IIFE: (function($) { //代码 } )(jQuery); 而不是直接的 function(){ jQuery... }
5.下面两个函数的返回值是一样的吗?为什么?
function foo1() { return { bar: "hello" }; } function foo2() { return //这里换行 { bar: "hello" }; } var o1 = foo1(); var o2 = foo2(); console.log(o1.bar); //hello console.log(o2.bar); //Uncaught TypeError: Cannot read property 'bar' of undefined 在编程语言中,基本都是使用分号(;)将语句分隔开,这可以增加代码的可读性和整洁性。 而在JS中,如若语句各占独立一行,通常可以省略语句间的分号(;),JS 解析器会根据能否正常编译来决定是否自动填充分号: var test = 1 + 2 console.log(test); //3 在上述情况下,为了正确解析代码,就不会自动填充分号了,但是对于 return 、break、continue 等语句,如果后面紧跟换行,解析器一定会自动在后面填充分号(;),所以第二个函数报错,第二段代码等价于: function foo2() { return; //这里换行 { bar: "hello" }; }
6.神马是 NaN,它的类型是神马?怎么测试一个值是否等于 NaN?
NaN 是 Not a Number 的缩写,JavaScript 的一种特殊数值,可以通过 isNaN(param) 来判断一个值是否是 NaN: console.log(isNaN(NaN)); // true console.log(isNaN(123)); // false console.log(isNaN("1111")); // false console.log(isNaN("1asd")); // true console.log(isNaN("asdaa222"));// true console.log(isNaN("'ssss'")); // true console.log(isNaN==isNaN); // true console.log(isNaN===isNaN); // true console.log(Object.prototype.toString.apply(isNaN)); // [object Function] console.log(Object.prototype.toString.call(isNaN)); // [object Function] console.log(typeof isNaN) // function
相关文章推荐
- JavaScript[容易忽视的错误]:当续行遇到换行,换行符丢失
- c语言语法容易忽视点
- JavaScript中的一些重要却容易被忽视的东西
- 细数 javascript 容易被忽略的语法陷阱
- javascript需要记忆又容易被忽视的基础
- Javascript中容易被忽视的地方
- js基本语法中容易忽视的几个地方
- 黑马程序员-Java学习笔记之容易让人忽视的环境变量配置和语法基础
- 细数 javascript 容易被忽略的语法陷阱
- [乐意黎转载]细数 javascript 容易被忽略的语法陷阱
- JavaScript中容易忽视的高效操作——位操作
- javaScript语法基础
- C++中一个容易被忽视的名字查找规则
- JavaScript的语法要点 2 - Scope Chain
- 【转载】谈谈javascript语法里一些难点问题(一)
- SQL开发中容易忽视的一些小地方(二)
- Javascript基础语法
- Javascript兼容性问题小结(容易导致浏览器不同,又不容易察觉的)
- JavaScript的一些基础语法
- Fragment使用容易忽视的问题