第 11 题:
var name = "erdong";
var object = {
name: "chen",
getNameFunc: function () {
return function () {
return this.name;
}
}
}
console.log(object.getNameFunc()());
解析:
// 输出
erdong
// 复制代码object.getNameFunc()(),先执行object.getNameFunc()返回一个函数:
function () {
return this.name;
}
// 复制代码返回的函数再执行,相当于
(function () {
return this.name;
})();
// 复制代码此时的this绑定为window。因此输出全局变量name的值erdong。
第 12 题
var name = "erdong";
var object = {
name: "chen",
getNameFunc: function () {
var that = this;
return function () {
return that.name;
}
}
}
console.log(object.getNameFunc()());
解析:
//输出
chen
object.getNameFunc()执行时,此时getNameFunc中的this绑定为object,因此that = object。object.getNameFunc()返回的函数再执行时,产生闭包,因此返回的函数也能访问到外层作用域中的变量that,因此object.name为object.name,即 chen。
第 13 题
(function() {
var a = b = 3;
})();
console.log(typeof a === 'undefined');
console.log(typeof b === 'undefined');
解析:
// 输出
true
false
首先要明白var a = b = 3是怎样执行的,伪代码:
b = 3;
var a = b;
因此在自执行函数执行时,b由于未经var等操作符声明,为全局变量。a为函数作用域中的局部变量。因此在外面访问a和b时,其值分别为ReferenceError: a is not defined和3。但是typeof检测未声明的变量不会抛出错误,会返回’undefined’。因此typeof a和typeof b分别返回’undefined’和’number’。
第 14 题
var a = 6;
setTimeout(function () {
a = 666;
}, 0)
console.log(a);
解析:
//输出
6
setTimeout为宏任务。即使设置延迟为0ms,也是等待同步代码执行完才会执行。因此console.log(a)输出 6
第 15 题
function fn1() {
var a = 2;
function fn2 () {
a++;
console.log(a);
}
return fn2;
}
var f = fn1();
f();
f();
解析:
// 输出
3
4
实参foo的值为{foo:{bar:1},因此typeof foo.bar为undefined。
typeof foo.foo.bar为number。
第 17 题
function f(){
return f;
}
console.log(new f() instanceof f);
解析:
//输出
false
由于构造函数f的返回值为f。因此new f()的值为f。所以console.log(new f() instanceof f)为console.log(f instanceof f),即 false。
第 18 题
function A () {
}
A.prototype.n = 1;
var b = new A();
A.prototype = {
n: 2,
m: 3
}
var c = new A();
console.log(b.n, b.m);
console.log(c.n, c.m);
解析:
// 输出
1,undefined
2,3
var b = new A(); 实例化b时,A的prototype为
A.prototype = {
constructor:A,
n:1
}
当访问b.n和b.m时,通过原型链找到A.prototype指向的对象上,即b.n = 1,b.m = undefined。
var c = new A(); 实例化c时,A的prototype为
A.prototype = {
n: 2,
m: 3
}
当访问a.n和a.m时,通过原型链找到A.prototype指向的对象上,此时A.prototype重写,因此a.n = 2,b.m = 3。
第 19 题
var F = function(){};
var O = {};
Object.prototype.a = function(){
console.log('a')
}
Function.prototype.b = function(){
console.log('b')
}
var f = new F();
F.a();
F.b();
O.a();
O.b();
解析:
// 输出
a
b
a
TypeError: O.b is not a function
F为函数,它也能访问Object原型上的方法,O为对象,不能访问Function原型上的方法。
F的原型链为:
F => F.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype
由于Object.prototype在F的原型链上,所以F能访问Object.prototype上的属性和方法。即: F.a(),F.b()能正常访问。
O的原型链为:
O => O.__proto__ => Object.prototype
由于Function.prototype不在O的原型链上,因此O不能访问Function.prototype上的方法,即O.b()抛出错误。
如果你对原型和原型链掌握的好,试着理解下面的示例:
console.log(Object instanceof Function);
console.log(Function instanceof Object);
console.log(Function instanceof Function);
第 20 题
function Person() {
getAge = function () {
console.log(10)
}
return this;
}
Person.getAge = function () {
console.log(20)
}
Person.prototype.getAge = function () {
console.log(30)
}
var getAge = function () {
console.log(40)
}
function getAge() {
console.log(50)
}
Person.getAge();
getAge();
Person().getAge();
new Person.getAge();
getAge();
new Person().getAge();
解析:
// 输出
20
40
10
20
10
30
Person.getAge();此时执行的是Person函数上getAge方法。
Person.getAge = function () {
console.log(20)
}
所以输出:20。
getAge();此时执行的是全局中的getAge方法。此时全局getAge方法为:
function () {
console.log(40)
}
所以输出:40。
Person().getAge();由于Person()单独执行所以,作用域中的this绑定为window,相当于window.getAge()。同上,执行的都是全局getAge 方法,但是Person执行时,内部执行了
getAge = function () {
console.log(10)
}
因此全局getAge方法现在为:
function () {
console.log(10)
}
所以输出:10。
new Person.getAge();此时相当于实例化Person.getAge这个函数,伪代码:
var b = Person.getAge;
new b();
// 所以输出:20
getAge();执行全局getAge方法,由于在Person().getAge()执行时把全局getAge方法赋值为:
function () {
console.log(10)
}
// 复制代码所以输出:10。
new Person().getAge();此时调用的是Person原型上的getAge方法:
Person.prototype.getAge = function () {
console.log(30)
}
// 复制代码所以输出:30。
// 这里要注意:1.变量提升及提升后再赋值。2.调用构造函数时,带()和不带()的区别。