试题汇总(持续更新~~~)

212 阅读2分钟

试题汇总

日常试题总结,巩固基础知识。

试题一

考点: 变量提升、作用域

var o = {
  fn: function(e) {
    console.log(e)
    console.log(fn)
  }
}

o.fn(1)
var fn = function(e) {
  console.log(e)
  console.log(fn)
}
fn(1)

以上代码可以等价于以下代码

var fn

var o = {
  fn: function(e) {
    console.log(e) // 1
    console.log(fn) // undefined
  }
}

o.fn(1)

fn = function(e) {
  console.log(e) // 1
  console.log(fn) // fn(全局)
}

fn(1)
  1. 当执行o.fn(1), 形参e为1,输出1, fn知识申明了并没有定义所以输出undefined
  2. fn(1),形参e为1,输出1, fn为全局的fn

试题二

考点:作用域、全局变量泄露、this绑定、new、变量提升

function Foo() {
  getName = function() {
    console.log(1)
  }
  return this
}

Foo.getName = function() {
  console.log(2)
}

Foo.prototype.getName = function() {
  console.log(3)
}

var getName = function() {
  console.log(4)
}

function getName() {
  console.log(5)
}

Foo.getName()
getName()
Foo().getName()
getName()
new Foo.getName()
new Foo().getName()
new new Foo().getName()
Foo.getName()

Foo.getName()比较好理解,函数是对象,Foo.getName就是在Foo上面定义了属性getName,所以直接输出 2

getName

getName() 这里要涉及到变量提升,以上代码等价于以下形式:

function getName(){
  console.log(5)
}
var getName
getName = function() {
  console.log(4)
}

所以这段代码会输出4

Foo().getName()

Foo().getName() 执行这里会引发全局变量泄露,this绑定

 function Foo() {
  getName = function() {
    console.log(1)
  } // 全局变量泄露 
  return this // this为全局变量
}

Foo().getName() // 1

由于Foo()内部没有使用var定义getName,所以getName会泄露在全局(window.getName),此时的this绑定规则为默认规则(绑定在全局),所以Foo().getName() 等价于 window,getName()

getName()

由第三步分析可知,此时执行getName()输出为1

new?

要弄清楚后面的事情必须要知道new究竟做了些什么。

  1. 创建(或者说构造)一个全新的对象。
  2. 这个新对象会被执行 [[ 原型 ]] 连接。
  3. 这个新对象会绑定到函数调用的 this。
  4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。
new Foo.getName()

在new后面跟一个普通函数,这个函数会正常执行,唯一的副作用是会返回一个新的对象。所以这里输出与直接执行Foo.getName()完全相同,所以输出2.

new Foo().getName()

等价于以下形式:

var obj = new Foo()
obj.getName()

所以这里getName()会查找到原型链上的 Foo.prototype.getName,所以输出3

这里有必要说一下为什么不是执行Foo.getName()

function Foo() {
  getName = function() {
    console.log(1)
  }
  this.getName = function() {
    console.log('getName')
  }
  return this
}

在new的第三步之后,你并没有在新建的这个对象上面添加方法getName,所以才会使用原型链上面的getName

new new Foo().getName()

等价于以下形式:

var obj = new Foo()
var obj2 = new obj.getName()

等价于 new Foo.prototype.getName() 所以输出为3

试题三

function fun(n,o) {
  console.log('A', n)
  console.log('A', o)
  return {
    fun: function(m) {
      console.log('B', m)
      console.log('B', o)
      return fun(m, n)
    }
  }
}

fun(0).fun(1)