【输出题】前端面试中判断输出顺序或内容的题目

71 阅读4分钟

var的作用域

百度一面

var res = []
var a = 3
var total = 0
function foo(a){
    for(var i = 0; i < 3; i++){
        res[i] = function(){
            total += i * a
            console.log(total)
        }
    }
}
foo(1)
res[0]() // 3
res[1]() // 6
res[2]() // 9

主要就是var作用域的一个考察。

foo(1)处,传入了一个参数a = 1,因此下面的res[i]执行时会首先找到这个a并使用它。 res[i]并没有将i作为参数传入到函数中,因此执行时会去foo中找i,而i经过循环后变成了3,所以每次 i * a都是 1 * 3total就从3 到 6 再到 9.

去哪儿二面

代码结果总结_代码 预计算结果有哪些

function print(n){
    for(var i = 0; i < n; i++){
        setTimeout(console.log, 1000, i) //这种写法第一个参数是回调函数,第二个参数是等待时间,第三个参数是回调函数的参数
    }
}
print(10)
// 1秒后输出0到9
function print(n){
    for(var i = 0; i < n; i++){
        setTimeout(console.log, 1000 * i, i)
    }
}
print(10) //每隔一秒输出一个
\\ 0
\\ 1
\\ 2
\\ 3
\\ 4
\\ 5
\\ 6
\\ 7
\\ 8
\\ 9

如何将上面每一秒输出一个数字的代码改为promise实现,代码如下

function print(n){
    for(var i = 0; i < n; i++){
        myPromise(i);
    }
}
function myPromise(i){
    return new Promise((resolve, )=>{
        setTimeout(()=>{
            console.log(i)
            resolve()
        }, 1000*i)
    })
}

变量与函数提升

变量提升:JS 解析器会把 var 声明的变量提升到,当前作用域最前面(只提升声明,不提升赋值);

函数提升:把 function 关键字声明的函数(命名函数)提升,当前作用域最前面; (只提升声明,不提升执行)

  • 函数声明会优先于var变量声明
  • 同一作用域下存在多个同名函数声明,后面的会替换前面的函数声明

作用域:es6之前是全局作用域函数作用域,ed6增加了块级作用域,但只有let和const会产生块级作用域

函数与变量同名案例

console.log(a); //f a(){console.log('funA')}
var a = 'varA';
console.log(a); // varA
function a() {
    console.log('funA');
}
a(); // error: a is not a function
//Example1
foo;
var foo = function () {
    console.log('foo1');
}
foo(); //foo1
var foo = function () {
    console.log('foo2');
}
foo();//foo2
//Example2
foo();
function foo() {
    console.log('foo1');
}
foo();
function foo() {
    console.log('foo2');
}
foo();
// foo2 foo2 foo2

函数提升优先级高于变量提升,且不会被同名变量声明时覆盖,但是会被同名变量赋值后覆盖。

  function a() {}
  var a = 1;
  console.log(typeof a)// number 
  
  function a() {}
  console.log(typeof a) //function
  var a = 1;

案例1

var num = 10
fn()
function fn(){
    console.log(num)
    var num = 20
}
console.log(num)

以上代码经过变量和函数声明提升后为以下代码

var num
function fn(){
    var num;
    console.log(num) //这里输出的是fn内部的num
    num = 20
}
num = 10
fn() //输出undefined
console.log(num) //输出全局num 10

案例2

var a = 18;
f1()
function f1() {
  var b = 9
  console.log(a)
  console.log(b)
  var a = '123'
}

变量和函数提升后相当于以下代码

var a
function f1() {
  var b
  var a
  b = 9
  console.log(a)
  console.log(b)
  a = '123'
}
a = 18
f1() // undefined 9

案例3 (典型面试题)

f1()
console.log(c)
console.log(b)
console.log(a)
function f1() {
  var a = b = c = 9
  console.log(a)
  console.log(b)
  console.log(c)
}

变量和函数提升后相当于以下代码

function f1() {
  var a = 9; b = 9; c = 9 //b和c没有用var声明,因此是一个全局变量
  console.log(a) //9
  console.log(b) //9 
  console.log(c)//9
}
f1()
console.log(c) //9
console.log(b) //9
console.log(a) //报错:a is not defined

面试题(哪家的记不清了)

var a = 20;
function bar() {
  console.log(a);
}
function foo(fn) {
  var a = 10;
  fn();
}
foo(bar); //20

相当于

var a;
function foo(bar) {
    function bar() {
      console.log(a);
    }
    var a;
    fn();
    a = 10
}
a = 20
foo(bar); //20

this指向

案例1 (富途笔试)

var a = 1
var b = 2
let obj = {
    a: 3
    b: 4
    getA: function(){
        var a = 5
        setTimeout(function(){
            console.log(this.a)
        }, 0) // setTimeout(callback, t)这里的callback是回调函数,被全局调用,this指向windows。如果是箭头函数的话则this指向obj
    }
    getB: function(){
        var b = 6
        return function(){
            console.log(this.b)
        }()
    }
}
obj.getA()
obj.getB() //getB执行后返回一个立即执行函数,而这个函数没有被其他对象调用,它的this指向windows

//输出 2 1(先输出的全局的b,再输出全局的a)

原型对象

原型对象中的this

原型对象中的this指向调用它的实例对象

function Book(){
    this.type = 'English'
}
Book.prototype.getType = function(){
    console.log(this.type)
}
book = new Book()
book.getType() // English
book.type = 'Math'
book.valueOf() // Book {type: 'Math'}

JavaScript 中的 valueOf() 方法用于返回指定对象的原始值,若对象没有原始值,则将返回对象本身。