JavaScript 经典面试题解析(持续更新)

1.说出并解释下列代码的输出结果:

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(); //2
Foo().getName(); //1
getName(); //1
new Foo.getName(); //2
new Foo().getName(); //3
new new Foo().getName(); //3

解析

(1) . Foo.getName()

直接调用 Foo 的静态方法 ,Foo.getName被重新复制,所以打印2

(2). Foo().getName()

Foo() 就是普通函数,返回的this是window,后面调用window.getName(),而winsow下的getName在第一步调用的时候被重新复制,所以打印1

(3). getName()

调用window中的getName,由于window中的getName在(2)中执行的时候被重新赋值,所以打印1.
(如果将(3)放在(2)前面执行,打印结果就为4)

(4). new Foo.getName()

同(1)效果一样,直接调用 Foo 的静态方法 ,Foo.getName被重新复制,所以打印2

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

通过实例访问 Foo原型链上的方法,所以打印3

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

首先 new Foo() 得到一个空对象 {}
第二步向空对象中添加一个属性 getName,值为一个函数
第三步 new {}.getName()
等价于 var bar = new (new Foo().getName)(); console.log(bar) 先 new Foo 得到的实例对象上的 getName 方法,再将这个原型上 getName 方法当做构造函数继续 new ,所以执行原型上的方法,打印 3

2.写出打印结果,并分析出原因

var a = 10
var obj = {
  a: 100,
  pro: {
    getPro: () => {
      console.log(this.a)
    },
  },
}
obj.pro.getPro() //10

解析

getPro是一个箭头函数的方法,在箭头函数中不会创建自己的this,只会集成作用于链上一层的this,所以这里的this指向为window,打印结果为10

3.写出打印结果,并分析出原因

var a = { n: 1 }
var b = a
a.x = a = { n: 2 }
console.log(a.x) // undefined
console.log(b.x)  // {n:2}

解析

首先,双等号的执行顺序是从左到右
那么a.x = a = {n:2} 就等价于 a.x = a ; a={n:2}
由于b = a 属于浅拷贝,那么再对a赋值时也会传递给b, 经过a.x处理过后b.x = {n:1},然后将{n:2}赋值给a同时会传递给b.x
此时的a={n:2} , b={n: 1,x: {n: 2}}
所以打印结果依次为 undefined , {n: 2}

4.写出打印结果,并分析出原因

var length = 10 

function fn(){
    console.log(this.length)
}
var obj = {
    length : 5 ,
    method :function (fn){
        fn();
        arguments[0]()
    }
}

obj.method(fn,1)

解析

首先,我在全局定义了一个变量length,一个对象obj和一个函数fn . length赋值为10。
接下来是fn函数,输出this.length,对象obj中obj.length是5,obj.method是一个函数,这个函数里面调用了fn函数,arguments是一个伪数组,代表method函数的实参
method函数当中调用的fn函数是全局当中的函数,所以this指向的是window,this.length就是10,arguments0代表的就是调用arguments里面的第一项,也就是传参进来的fn,所以这个this指向的就是arguments,arguments.length的值为2
所以最后的打印结果为10 ,2

5.写出打印结果,并分析出原因

function a(xx){
    this.x = xx
    return this
}

var x = a(5)
var y = a(6)

console.log(x.x)
console.log(y.x)

解析

首先,我们在全局定义了一个变量x,一个变量y,和一个函数a,函数a当中的this.x等于接受到的参数,返回this,.这里要注意,返回的是this,不是this.x 接下来我们给X赋值 值为a(5) ,又给y赋值,值为a(6).最后我们输出x.x 和y.x

分析完代码的定义, 我们来看输出结果, a(5) 执行的时候传递一个参数为5,调用函数a, 返回this 此时的this指向window, 所以 x = window , 但是后面又执行了y=a(6), 再次调用fn 将 this.x修改为6, 所以此时window中的 x 为6, 返回结果为window, 所以y=window,
由于 x =6 所以x.x = undefined, y=window, window中的x为6 , 所以y.x 为 6
打印结果依次为 undefined 和 6

6.阅读下面代码,写出打印结果的先后顺序

new Promise(function (resolve, reject) {
        console.log('A')
        resolve()
      }) //A J B H K C I L D G E F
        .then(function (resolve, reject) {
          new Promise(function (resolve, reject) {
            console.log('B')
            resolve()
          })
            .then(function () {
              console.log('c')
            })
            .then(function () {
              new Promise(function (resolve, reject) {
                console.log('D')
                resolve()
              })
                .then(function () {
                  console.log('E')
                })
                .then(function () {
                  console.log('F')
                })
              console.log('G')
            })
          console.log('H')
        })
        .then(function () {
          console.log('I')
        })

      new Promise(function (resolve, reject) {
        console.log('J')
        resolve()
      })
        .then(function () {
          console.log('K')
        })
        .then(function () {
          console.log('L')
        })
打印结果

A J B H K C I L D G E F

解析:

注:下文中的轮次只是为了方便理解
首先,我们来看最外层的两个newPromise,里面同步语句会先执行,所以最先打印出来的是A和J
因为每个Promise都会产生一个微任务,所以到第一轮的微任务中Promise的第一个then会进入到第一轮的微任务中,下面我们来单独看这两个then. 第一个Promise的第一个then里面又new了一个新的Promise,这个新的Promise产生一个微任务,本轮的微任务已经在执行中了,所以这个微任务会排到下一个微任务队列的第一位,还是先执行里面的同步语句,打印B和H ,之后运行低二个Promise的第一个then,打印K

第一轮的微任务执行完毕,开始第二轮微任务,先执行第三个Promise的第一个then,打印C,继续执行第一个Promise的第二个then,打印I,最后执行第二个Promise的第二个then,打印K
第三轮微任务开始,执行第三个Promise的第二个then,这个then里面又new了一个新的Promise,同理,新的Promise(第四个)产生的微任务放入下一轮第一个执行,此时执行同步语句,打印D和G
第四轮微任务开始执行第四个Promise的第一个then,打印E
第五轮微任务开始执行第四个Promise的第二个then,打印F
综上,我们最后得到的结果就是:
A
J
B
H
K
C
I
L
D
G
E
F

7.阅读下面代码,写出他们的打印顺序

 new Promise((resolve,reject)=>{
  console.log('A')
  setTimeout(() => {
    console.log('B')
  }, 0);
  console.log('C')
  resolve()
  console.log('D')
}).then((resolve,reject)=>{
  console.log('E')
  new Promise((resolve,reject)=>{
    console.log("F")
    resolve()
    console.log('G')
  }).then(()=>{
     setTimeout(()=>{
       console.log('H')
     })
    console.log('I')
  }).then(()=>{
    console.log('J')
  })
}).then(()=>{
  console.log('K')
})
setTimeout(() => {
  console.log('L')
}, 0);
new Promise((resolve,reject)=>{
  console.log('M')
  resolve()
}).then(()=>{
  setTimeout(() => {
    new Promise((resolve,reject)=>{
      console.log('N')
      resolve()
    }).then(()=>{
       setTimeout(()=>{
         console.log('O')
       },0)
    }).then(()=>{
      console.log('p')
    })
  }, 0);
})
console.log('Q')
打印结果

ACDMQEFGKJBLNPHO

解析

首先,我们要知道微任务会先于宏任务执行,知道了这一点,我们来看下面的代码.
现在,我们将微任务列表和宏任务列表分开梳理,最后再合并结果
先看微任务,第一层为Promise--promise--console.log,第一个Promise中的setTimeOut创建宏任务1,最外层的setTimeOut创建宏任务2
所以第一轮按从上到下顺序打印 A,C,D,M,Q

然后看第二轮微任务,分别为第一个Promise中的then,和第二个Promise中的then,由于第二个Promise中的then中执行setTimeOut,创建宏任务3,所以第二轮先打印 E,然后创建Promsie,打印F和G,目前的及结果为A,C,D,M,Q,E,F,G

然后看第三轮,由于第二个Promise中的then中创建了宏任务,所以第三轮微任务只在第一个promise中的第二个then中,从代码中可以看出,第一个Promise中的第一个then执行后,有两个then,前者创建宏任务4,打印I,后者打印K,所以目前打印顺序为A,C,D,M,Q,E,F,G,I,K

然后第四轮微任务只剩下第三轮中的第二个then所调用的then了,打印结果为J,至此,微任务已经执行完毕,结果顺序为:
A,C,D,M,Q,E,F,G,I,K,J

开始执行宏任务,第一轮按上方创建顺序为宏任务1,2,3,4
宏任务1打印B,宏任务2打印L,宏任务3 第一轮微任务打印N,然后第二轮创建宏任务5,第三轮打印P, 宏任务4打印H
第一轮宏任务 打印顺序为B,L,N,P,H

第二轮宏任务执行宏任务3创建的宏任务5,打印O
至此,宏任务执行完毕,结果为B,L,N,P,H

由于宏任务是在微任务执行完成后执行,所以需要将宏任务的打印结果连接在微任务后方,结果为
A
C
D
M
Q
E
F
G
I
K
J
B
L
N
P
H
O

8.力扣 - 柠檬水找零

在柠檬水摊上,每一杯柠檬水的售价为5美元
顾客排队购买你的产品,(按账单bills支付的顺序)一次购买一杯
每位顾客只买一杯柠檬水,然后向你付5美元、10美元或者20美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付5美元
注意,一开始你手头没有任何零钱
如果你能给每位顾客正确找零,返回true,否则返回false

function func(bills) {
  let a = 0 //5元
  let b = 0 //10元
  //循环所有数据
  for (let i = 0; i < bills.length; i++) {
    //如果顾客给的是5元
    if (bills[i] === 5) {
      // 手中的5元加一
      a += 1
    } else if (bills[i] === 10) {
      //顾客给的是10元
      //手中的5元减一,10元加一
      b += 1
      a -= 1
    } else {
      //顾客给的是20元,有两种找零方式
      // 找3个5元, 或者找1个10元1个5元
      if (b >= 1) {
        //10元足够的时候优先找一个10元一个5元
        //10元减一,5元减一
        a -= 1
        b -= 1
      } else {
        //10元不够是找三个5元, 5元减3
        a -= 3
      }
    }
    //当5元也不够时说明没有零钱了,返回false
    if (a < 0) {
      return false
    }
  }
  //循环完成,说明零钱足够,返回true
  return true
}

let result = func([5, 5, 5, 10, 20])
console.log(result)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容