1、使用 typeof bar === "object" 判断 bar 是不是一个对象有神马潜在的弊端?如何避免这种弊端?
使用 typeof 的弊端是显而易见的(这种弊端同使用 instanceof):
let obj = {};
let arr = [];
console.log(typeof obj === 'object'); //true
console.log(typeof arr === 'object'); //true
console.log(typeof null === 'object'); //true
从上面的输出结果可知,typeof bar === "object" 并不能准确判断 bar 就是一个 Object。可以通过 Object.prototype.toString.call(bar) === "[object Object]" 来避免这种弊端:
let obj = {};
let arr = [];
console.log(Object.prototype.toString.call(obj));
//[object Object]
console.log(Object.prototype.toString.call(arr));
//[object Array]
console.log(Object.prototype.toString.call(
null
));
//[object Null]
另外,为了珍爱生命,请远离 ==:
2、下面的代码会在 console 输出神马?为什么?
(function(){
var a = b = 3;
})();
console.log("a defined? " + (typeof a !== 'undefined')); //a defined? true
console.log("b defined? " + (typeof b !== 'undefined'));//b defined? true
console.log(b);
//3
console.log(
typeof
a);
//object
3、下面的代码会在 console 输出神马?为什么?
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);//outer func: this.foo = bar
console.log("outer func: self.foo = " + self.foo);//outer func: self.foo = bar
(function() {
console.log("inner func: this.foo = " + this.foo);//undefined
console.log("inner func: self.foo = " + self.foo);//inner func: this.foo = bar
}());
}
};
myObject.func();
4、将 JavaScript 代码包含在一个函数块中有神马意思呢?为什么要这么做?
换句话说,为什么要用立即执行函数表达式(Immediately-Invoked Function Expression)。
for
(
var
i = 0; i < 5; i++) {
setTimeout(
function
() {
console.log(i);
}, 1000);
}
//55555
for
(
var
i = 0; i < 5; i++) {
(
function
(i) {
setTimeout(
function
() {
console.log(i);
}, 1000);
})(i)
}
//1234
而在 JQuery/Node 的插件和模块开发中,为避免变量污染,也是一个大大的 IIFE:
(function($) {
//代码
} )(jQuery);
5、在严格模式('use strict')下进行 JavaScript 开发有什么好处?
消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫。
6、下面两个函数的返回值是一样的吗?为什么?
function
foo1()
{
return
{
bar:
"hello"
};
}
function
foo2()
{
return
{
bar:
"hello"
};
}//return 、break、continue 返回undefined
7、神马是 NaN,它的类型是神马?怎么测试一个值是否等于 NaN?
NaN 是 Not a Number 的缩写,JavaScript 的一种特殊数值,其类型是 Number,可以通过 isNaN(param) 来判断一个值是否是 NaN:
console.log(isNaN(NaN));
//true
console.log(isNaN(23));
//false
console.log(isNaN(
'ds'
));
//true
console.log(isNaN(
'32131sdasd'
));
//true
console.log(NaN === NaN);
//false
console.log(NaN === undefined);
//false
console.log(undefined === undefined);
//false
console.log(
typeof
NaN);
//number
console.log(Object.prototype.toString.call(NaN));
//[object Number]
9、实现函数 isInteger(x) 来判断 x 是否是整数
可以将 x 转换成10进制,判断和本身是不是相等即可:
function isInteger(x) {
return parseInt(x, 10) === x;
}
ES6 对数值进行了扩展,提供了静态方法 isInteger() 来判断参数是否是整数:
Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false
Number.isInteger("15") // false
Number.isInteger(true) // false
10、在下面的代码中,数字 1-4 会以什么顺序输出?为什么会这样输出?
(
function
() {
console.log(1);
setTimeout(
function
(){console.log(2)}, 1000);
setTimeout(
function
(){console.log(3)}, 0);
console.log(4);
})();
//1432
11、写一个少于 80 字符的函数,判断一个字符串是不是回文字符串
function isPalindrome(str) {
str = str.replace(/\W/g, '').toLowerCase();
return (str == str.split('').reverse().join(''));
}
12、写一个按照下面方式调用都能正常工作的 sum 方法
console.log(sum(2,3));
// Outputs 5
console.log(sum(2)(3));
// Outputs 5
function sum() {
var fir = arguments[0];
if(arguments.length === 2) {
return arguments[0] + arguments[1]
} else {
return function(sec) {
return fir + sec;
}
}
}
for
(
var
i = 0; i < 5; i++) {
var
btn = document.createElement(
'button'
);
btn.appendChild(document.createTextNode(
'Button '
+ i));
btn.addEventListener(
'click'
,
function
(){ console.log(i); });
document.body.appendChild(btn);
}
1、点击 Button 4,会在控制台输出什么?//点击随意一个都会输出5
14、下面的代码会输出什么?为什么?
var
arr1 =
"john"
.split(
''
); j o h n
var
arr2 = arr1.reverse(); n h o j
var
arr3 =
"jones"
.split(
''
); j o n e s
arr2.push(arr3);
console.log(
"array 1: length="
+ arr1.length +
" last="
+ arr1.slice(-1));//
array 1: length=5 last=j,o,n,e,s
console.log(
"array 2: length="
+ arr2.length +
" last="
+ arr2.slice(-1));//array2: length=5 last=j,o,n,e,s
15、下面的代码会输出什么?为什么?
console.log(1 +
"2"
+
"2"
);//122
console.log(1 + +
"2"
+
"2"
);//32
console.log(1 + -
"1"
+
"2"
);//02
console.log(+
"1"
+
"1"
+
"2"
);//112
console.log(
"A"
-
"B"
+
"2"
);//NaN2
console.log(
"A"
-
"B"
+ 2);//NaN
输出什么,自己去运行吧,需要注意三个点:
多个数字和数字字符串混合运算时,跟操作数的位置有关
console.log(2 + 1 + '3'); / /‘33'
console.log('3' + 2 + 1); //'321'
数字字符串之前存在数字中的正负号(+/-)时,会被转换成数字
console.log(
typeof
'3'
);
// string
console.log(
typeof
+
'3'
);
//number
同样,可以在数字前添加 '',将数字转为字符串
console.log(
typeof
3);
// number
console.log(
typeof
(
''
+3));
//string
console.log(
'a'
*
'sd'
);
//NaN
console.log(
'A'
-
'B'
);
// NaN
可以参考此篇:从作用域链谈闭包
18、下面的代码会输出什么?为啥?
for
(
var
i = 0; i < 5; i++) {
setTimeout(
function
() { console.log(i); }, i * 1000 );
}//5
19、解释下列代码的输出
console.log(
"0 || 1 = "
+(0 || 1));//1
console.log(
"1 || 2 = "
+(1 || 2));//1
console.log(
"0 && 1 = "
+(0 && 1));//0
console.log(
"1 && 2 = "
+(1 && 2));//2
console.log(1 && 2 && 0);
//0
console.log(1 && 0 && 1);
//0
console.log(1 && 2 && 3);
//3
如果某个操作数为 false,则该操作数之后的操作数都不会被计算
逻辑或返回第一个是 true 的操作数 或者 最后一个是 false的操作数console.log(1 || 2 || 0);
//1
console.log(0 || 2 || 1);
//2
console.log(0 || 0 ||
false
);
//false
如果某个操作数为 true,则该操作数之后的操作数都不会被计算
如果逻辑与和逻辑或作混合运算,则逻辑与的优先级高:
console.log(1 && 2 || 0);
//2
console.log(0 || 2 && 1);
//1
console.log(0 && 2 || 1);
//1
在 JavaScript,常见的 false 值:
0, '0', +0, -0, false, '',null,undefined,null,NaNconsole.log([] ==
false
)
//true
console.log({} ==
false
)
//false
console.log(Boolean([]))
//true
console.log(Boolean({}))
//true
20、解释下面代码的输出
console.log(false == '0')//true
console.log(false === '0')//false
21、解释下面代码的输出
var
a={},
b={key:
'b'
},
c={key:
'c'
};
a[b]=123;
a[c]=456;
console.log(a[b]);
22、解释下面代码的输出
console.log((function f(n){return ((n > 1) ? n * f(n-1) : n)})(10));//3628800
结果是10的阶乘。这是一个递归调用,为了简化,我初始化 n=5,则调用链和返回链如下:
23、解释下面代码的输出
(
function
(x) {
return
(
function
(y) {
console.log(x);
})(2)
})(1);//输出1,闭包能够访问外部作用域的变量或参数。
24、解释下面代码的输出,并修复存在的问题
ar
hero = {
_name:
'John Doe'
,
getSecretIdentity:
function
(){
return
this
._name;
}
};
var
stoleSecretIdentity = hero.getSecretIdentity;
console.log(stoleSecretIdentity());
console.log(hero.getSecretIdentity());
var
stoleSecretIdentity =
function
(){
return
this
._name;
}
stoleSecretIdentity
的上下文是全局环境,所以第一个输出 undefined。若要输出 John Doe,则要通过 call 、apply 和 bind 等方式改变 stoleSecretIdentity 的this 指向(hero)。
第二个是调用对象的方法,输出 John Doe。
25、给你一个 DOM 元素,创建一个能访问该元素所有子元素的函数,并且要将每个子元素传递给指定的回调函数。
函数接受两个参数:
- DOM
- 指定的回调函数
原文利用 深度优先搜索(Depth-First-Search) 给了一个实现:
function
Traverse(p_element,p_callback) {
p_callback(p_element);
var
list = p_element.children;
for
(
var
i = 0; i < list.length; i++) {
Traverse(list[i],p_callback);
// recursive call
}
}