题目很经典,设计了构造函数,构造函数的静态成员,构造函数的原型对象,函数作用域,arguments以及new的关键字
题目一、
题目:
// 面试题一
function Foo(){
getName = function(){ alert(1); };
return this;
}
function getName(){
alert(5);
}
Foo.getName = function(){ alert(2); };
Foo.prototype.getName = function(){ alert(3); };
getName = function(){ alert(4); };
// 请写出答案
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
=写出答案后再看下面更好哦=
解析:
// 面试题一解析
// 构造函数
function Foo(){
// 构造函数里面属性,只要执行了,就会覆盖全局的getName方法
getName = function(){ alert(1); };
return this;
}
// 全局方法,被后面的匿名函数覆盖
function getName(){
alert(5);
}
// 构造函数的静态成员
Foo.getName = function(){ alert(2); };
// 构造函数的原型上挂载的方法,即给实例对象使用
Foo.prototype.getName = function(){ alert(3); };
// 全局函数,会覆盖全局getName的方法
getName = function(){ alert(4); };
// 注意点一:代码是从上往下执行
// 注意点二:new 只和最近的函数调用结合
// 注意点三:函数不是看在哪个位置,而是看是谁调用了(通过什么方式调用)
// 解析如下:
Foo.getName();
// 调用构造函数的静态成员 即2
getName();
// 匿名函数覆盖了之前的函数,所以是4
Foo().getName();
// 执行了Foo构造函数,return了this,这个this执向window,因为构造函数本身也是函数,所以就是window调用getName方法并且把全局方法覆盖了,即1
getName();
// 因为上一个执行了,把全局方法覆盖了,所以是1
new Foo.getName();
// new和 Foo.getName()结合,即2
new Foo().getName();
// new先和Foo()结合,得到Foo()的实例对象,实例对象的getName方法就是挂载在Foo构造函数原型上的方法,即3
new new Foo().getName();
// 先执行第二个new,得到3,又new了3,所以还是3
// 答案是 2 4 1 1 2 3 3
题目二、
题目:
// 面试题二
var length = 10;
function fn() {
console.log(this)
console.log(this.length)
}
var obj = {
length: 5,
method: function (fn) {
fn();
arguments[0]()
}
}
obj.method(fn,1)
=写出答案后再看下面更好哦=
解析:
// 面试题二
// 全局变量
var length = 10;
// fn函数
function fn() {
console.log(this)
console.log(this.length)
}
// obj对象包含一个属性,1个method方法
var obj = {
length: 5,
method: function (fn) {
fn();
arguments[0]()
}
}
obj.method(fn,1)
// 调用obj的method方法,传递2个实参 fn和1
// method方法只接收1个形参,所以只传递了fn进去
// fn():即是普通函数的调用,所以this指向window,length是10
// arguments[0]是指第1项的实参,即fn;arguments是一个伪数组(所有实参的数组),相当于是这个伪数组调用了fn函数,所以指向arguments,所以是数组的长度为2
// 答案 10,2
// 注意: 1.fn()调用就是window调用,省略了window 2.fn不看在哪个位置,只看是谁调用了或者说是通过什么方式调用了。