网上看到一篇搜集一些关于JavaScript基础的题目,试着自己解答了一下。
原文在这:http://zxhfighter.github.io/blog/javascript/2013/03/14/javascript-quiz.html
-
关于arguments
// PS: IIFE(Immediately-Invoked Function Expression),即自调用函数、立即执行函数
// quiz-1:该IIFE返回什么结果?
(function(){
return typeof arguments;
})();
answer: “object”,arguments是具有length属性的类数组对象
// quiz-2:该IIFE返回什么结果?
(function(){
return Object.prototype.toString.call([]).slice(8, -1);
})();
answer: 借助call方法来调用toString方法返回一个字符串"[object Arguments]",然后截取指定的长度返回:"Arguments"
// quiz-3:该IIFE返回什么结果?
(function(){
return Object.prototype.toString.call([].slice.call(arguments)).slice(8, -1);
})(1,'2',new Date(),4);
answer: [].slice.call(arguments)已经将对象转换为数组,调用toString后返回"[object Array]",最后返回 "Array"
// quiz-4:console.log输出什么?
function b (x, y, a) {
arguments[2] = 10;
console.log(a);
}
b(1,2,3);
answer: arguments与形参在传入的参数之间保持着的映射关系(并非指向同一个对象),改变其一,另一个对象中的参数也会改变.输出:10
// quiz-5:f()输出什么?
function f(x, y) {
x = 10;
console.log(
arguments[0],
arguments[1]
);
}
f();
answer: 上面已经说明,映射关系只针对传入的参数,这里没有传参,所以arguments与形参之间没有关联。故输出:undefined,undefined
-
关于函数表达式
// quiz-1:typeof g()结果为?
var f = function g() { return 42; };
typeof g();
answer: 函数表达式中的函数名的作用范围如果遵循规范的话是仅限于函数体内的,所以在标准浏览器中这里会报引用错误(IE浏览器中的结果则会不一样)
// quiz-2:下面的IIFE返回什么?
(function(f){
return typeof f();
})(function(){ return 1; });
answer: number,多绕了一下而已
// quiz-3:typeof f的值?
var f = (function f() {
return '1';
}, function g() {
return 2;
})();
typeof f;
answer: number,了解逗号运算符的作用
-
关于变量声明和运算顺序
// quiz-1:x的值?
var y = 1, x = y = typeof x;
x
answer: 需了解JavaScript中变量的预解析机制,从右到左的赋值顺序,所以,此处x为undefined
// quiz-2:a的值?
var a = 1;
var b = function a (x) {
x && a(--x);
};
console.log(a);
answer: 函数表达式不会影响变量对象,可以参考上一篇博文,故a为1
// quiz-3:下面表达式的值?
(1, 5-1) * 2
answer:8,考察逗号运算符的作用
// quiz-4:下面几条语句输出?
var b = 10,
c = (
20,
function(x) {return x + 100},
function() {return arguments[0]}
);
a = b + c
({x:10}).x
answer: 这题最初没大看懂,最后看结果才明白。其实是一条语句分两行写了而已,a=b+c({x:10}).x,写成这样的话就可以直接看出来了,结果:20
-
关于变量提升
// quiz-1:写出所有输出结果
var abc = 'global_var';
(function(){
console.log(typeof abc);
console.log(typeof fun_1);
console.log(typeof fun_2);
var abc = 'local_var';
function fun_1() {}
var fun_2 = function (){};
console.log(typeof abc);
console.log(typeof fun_1);
console.log(typeof fun_2);
})(window);
answer: 变量提升就是在代码执行时,刚进入一个上下文的时候,所有的变量申明,函数申明都会第一个被解析,犹如所有的申明都放在顶部一样。而给变量的赋值操作则仍然在原来的位置,执行到它的位置时,才会赋值,此前要不就是undefined,要不就是reference a function, 所以,懂了这个就很简单的了。输出:
undefined,undefined,function,undefined,string,function,function
// quiz-2:x的值?
var x = 1;
if (function f(){}) {
x += typeof f;
}
x
answer: 此题要明白两点。1,圆括号中只能包含表达式语句,因此,里面的是函数表达式而不是函数申明,所以在标准浏览器中f只在函数内部可以访问,外部访问不到;2,任何非null的对象转为布尔型时都为真。所以结果为:"1undefined"
// quiz-3:iife返回结果?
(function(){
function f() { return 1; }
return f();
function f() { return 2; }
})(window);
answer: 同样的,函数申明置顶机制,在执行return 语句之前,两个函数申明都已经被解析,存储在变量对象中了。因此,结果为:2
// quiz-4:a的值?
function a (x) {
return x * 2;
}
var a;
console.log(a);
answer: 可参考上一篇文章,变量申明不会干扰函数申明,所以输出的是函数本身//ps:如果是var a=1,结果则不一样了.
// quiz-5:iife返回结果?
(function(){
a = function() { return 1; };
function a () {
return 2;
}
var a;
return a;
})(window);
answer: 函数表达式的赋值,顺序在函数申明和变量申之后,故最后a 是return 1 的函数
-
关于delete运算符
// quiz-1:写出所有输出
var global_var = 1;
(function(x){
global_var_imply = '2';
var local_var = 3;
var arr = [1,2,3,4,5];
var obj = {x:1, y:2, z:3};
delete(global_var)
delete(global_var_imply)
delete(local_var)
delete(x)
delete(arr[2])
delete(obj.y)
console.log(typeof global_var);
console.log(typeof global_var_imply);
console.log(typeof local_var);
console.log(typeof x);
console.log(arr);
console.log(arr.length);
console.log(obj);
})(1);
answer: 记住
1,函数形参和通过var申明的变量具有不能删除的特性,而没有var申明的隐式全局变量实际上是全局对象的一个属性,是可以被delete的。
2,对象的属性是可以被删除。
3,delete删除数组中的元素其实把数组中的元素置为undefined,数组长度并未变化。
-
关于this
// quiz-1:下面两个iife的返回结果?
var foo = {
bar: function () {
return this.baz;
},
baz: 1
};
(function(){
return typeof arguments[0]();
})(foo.bar);
(function(){
return typeof arguments[0].call(foo);
})(foo.bar);
answer: undefined,1;第一个经过参数传递并没有绑定this,故调用时,this已经变为window了,而第二个则使用call方法明确指定了this为foo对象
// quiz-2:typeof返回结果?
var foo = {
bar: function () {
return this.baz;
},
baz: 1
};
typeof (f = foo.bar)();
answer: undefined,可以看作全局属性 f 保存了指向 bar 方法的地址,调用的时候实际上是 window.f() 的形式了,故this为window。
// quiz-3:写出所有输出
var x = 10;
var foo = {
x: 20,
bar: function () {
var x = 30;
return this.x;
}
};
console.log(
foo.bar(),
(foo.bar)(),
(foo.bar = foo.bar)(),
(foo.bar, foo.bar)()
);
answer: 20,20,10,10,后两者经过运算之后调用模式已经改变。详细可以参考大叔的博客this篇.
-
关于typeof
// quiz-1:写出下面几个typeof的结果
var x = [typeof x, typeof y][1];
typeof typeof x;
typeof typeof(null);
typeof foo == 'undefined';
typeof foo === 'undefined';
answer: 多走了几步而已,看懂每一步即可得出最后结果:string,string,true,true
-
关于JSON对象
// quiz-1:iife的返回结果?
(function(foo){
return typeof foo.bar;
})({foo: {bar: 1}});
answer: undefined
-
关于类和对象
// quiz-1:true or false?
function F() { return F; }
new F() instanceof F
answer: false,主要考察构造函数的创建新对象的时候的一些操作,其中包括将自身prototype属性指向的对象作为给新生成的对象的原型,而这里生成的是自己,也是一个函数,故也是Function的实例。new F() instanceof Function //true
// quiz-2:下面运行结果输出什么?
100.toString.length
100['toString']['length'];
100 .toString();
(100).toString();
1..z;
answer: SyntaxErro,1,”100”,”100”,undefined;
第一个100是基本类型,没有转为自动包装类型就调用了方法,当然会报语法错误。
第二个100通过[]的调用方式,调用之前会自动转换类型,因此,实际上是Number对象调用toString方法,参数只有一个,故length为1
第三个和第四个都可以转换为自动包装类型,输出100的字符串表示
第五个中第一个"."表示小数点,第二个才是调用方法,其过程也可以转换为自动包装类型,而转换后调用合法,但没有z这个属性,故输出undefined
-
关于with
// quiz-1:输出结果
with (function(x, undefined){}) length
answer: 考察with的作用,若没有with语句则,length 等同于window.length,又来with语句之后,length等同于(function(x,undefined){}).length,值为函数的参数个数:2
-
关于++
// quiz-1:result的值?
var num1 = 5, num2 = 6, result = num1+++num2;
result
answer: num1先提取值进行运算然后自加1,故result = 11
-
关于作用域
// quiz-1:a的值?
if (!("a" in window)) {
var a = 1;
}
console.log(a);
answer: undefined,变量预解析机制
-
关于setTimeout
// quiz-1:o.doIt()的输出?
var x = 5;
var o = {
x: 10,
doIt: function doIt() {
var x = 20;
var timer = setTimeout(function() {
console.log(this.x);
}, 10);
}
};
o.doIt();
answer:5,setTimeout函数中的作用域是全局作用域
-
关于字符串和数字的比较和转换
// quiz-1:写出所有输出
var num1 = '10', num2 = '9';
console.log(num1 < num2);
console.log(+num1 < num2);
console.log(num1 + num2);
console.log(+num1 + num2);
answer:考察运算符左右两边类型不同时的转换规则,true,false,”109”,”109”,具体可参考JavaScript高级程序设计一书
-
关于字符串截断
// quiz-1:写出所有输出
var msg = 'Hello, world';
msg.substring(1,4)
msg.substr(1,4)
msg.slice(1,4)
answer: ell,ello,ell
-
关于valueOf和toString
// quiz-1:写出所有输出
var obj = {
x: 8,
valueOf: function() {
return this.x + 2;
},
toString: function() {
return this.x.toString();
}
};
console.log(obj + 1);
obj < "9"
answer: 11,false,考察运算符左右两边类型不同时的转换规则,true,false,”109”,”109”,具体可参考JavaScript高级程序设计一书
-
关于parseInt
// quiz-1:两个parseInt的值?
parseInt('06')
parseInt('08')
answer: 主要考察parseInt在部分浏览器中转换一些有前导0的数字,如果没有指定转换的进制数,有可能会转为8进制,所以实际编程中更应该这样写parseInt(‘08’,10);
-
关于对象初始化
// quiz-1:函数执行结果?
({
x: 10,
foo: function () {
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
with (this) {
var x = 20;
var y = 30;
bar.call(this);
}
}
}).foo();
answer: 调用foo方法的对象是自身,with中会改变原有的x属性值,且申明了变量y,bar.call(this)调用的结果为:,undefined,30,20