🚀
头像

默永


人生就像骑单车,想保持平衡就得往前走。

面试题JS三座大山

2022-10-25 17:16:11 292 💗 0 @默永
  1. 原型和原型链
  2. 作用域与闭包
  3. 异步和单线程

01、如何判断一个变量是不是数组

考察点:instanceof的掌握

参考答案:

function isArray(obj){
 if (obj instanceof Array) {
return true
 } else {
return false
 }
}
instanceof 可以判断是不是由这个class构建的

扩展知识:

【原型】
console.log(stu.__proto__) 隐式原型
console.log(Student.prototype) 显示原型
console.log(Student.prototype === stu.__proto__)
每个类都有显示原型、每个实例都有隐式原型
实例的隐式原型__proto__指向类的显示原型prototype
【原型链】
console.log(Student.prototype.__proto__)
console.log(People.prototype)
console.log(Student.prototype.__proto__ === People.prototype)


02、如何使⽤class实现继承?

class ⼦类 extends ⽗类 {
 constructor() {
  super()
 }
}

作⽤域与闭包

串讲:

  • 作⽤域 —— 变量的合法使⽤范围。全局作⽤域、函数作⽤域、块级作 ⽤域
  • ⾃由变量 —— ⼀个变量在当前作⽤域没有定义,但被使⽤了
  • 闭包(56T) —— 所有⾃由变量的查找,是在函数定义的地⽅向上级作 ⽤域查找

03、this在不同场景下如何取值?

参考答案:

this的值是什么,取决于调⽤什么时候,与定义⽆关
// 在普通函数
function fn(){
  alert(this) // this -> window
}
fn()
// 使⽤ call、apply、bind
let fn2 = fn.bind({a:'abc'})
fn2() // this -> {a:'abc'}
// 对象⽅法调⽤
let obj={
  name: 'abc',
  getName(){
    this.name // this -> 当前对象
  },
  test(){
   setTimeout(() => {
     this // this -> 当前对象,箭头函数中this的值是上级作⽤的this
   })
 }
  test2(){
    setTimeout(function(){
      this // this -> window
    })
  }
}
// 在class中
// 在箭头函数中

04、⼿写bind函数

Function.prototype.bind1=function (){
  const args=Array.prototype.slice.call(arguments)
  const targetThis=args.shift()
  const _this=this
  return function (){
    return _this.apply(targetThis, args)
  }
}

05、阅读代码,填写结果

function foo(fn){
  const a=200;
  fn()
}
const a=100;
function fn() {
  console.log(a)
}
foo(fn) // 结果是多少? 100

06、阅读代码,填写结果

function foo() {
  const a=100;
  return function (){
    console.log(a)
  }
}
const fn=foo();
const a=200;
fn() // 结果是?? 100

07、实际开发中闭包的应⽤场景,举例说明

参考答案:

// 隐藏数据,数据被隐藏,外部⽆法访问
function myData(){
  let data={}
  return {
    setData(key, value){
      data[key]=value
    },
    getData(key) {
      return data[key ]
    }
  }
}

(function (){

})()

// 事件中获得正确的下标 ⻅ “闭包应⽤”
for (var i = 0; i < aBtn.length; i++) {
  (function (index) {
    aBtn[i].addEventListener("click", function () {
      alert(index);
    });
  })(i);
}

08、阅读代码,填写结果

// ⻚⾯中有3个按钮
let aBtn=document.getElementsByClassName('btn')
for (var i=0; i<aBtn.length; i++) {
  aBtn[i].addEventListener('click', function (){
    alert(i) // 每个按钮点击时,i的值分别是什么?
  })
}
//都为3

异步和单线程

09、阅读代码,填写结果

console.log(1)
setTimeout(() => {
  console.log(2)
}, 1000)
console.log(3)
setTimeout(() => {
  console.log(4)
}, 0)
console.log(5)

// 1、3、5、4、2

参考答案:

js是单线程语⾔
 js和DOM渲染共⽤同⼀个线程,因为JS可以修改DOM结构

先把同步代码执⾏完,再执⾏异步的代码

10、同步和异步的区别是什么?

参考答案:

同步就是⼀件事做完再做下⼀件事,异步是多件事情⼀起做
同步阻塞代码执⾏,异步不阻塞代码执⾏
 同步:alert demo
 异步:setTimeout setInterval ajax

11、⼿写Promise加载⼀张图⽚

参考答案:

let url = '';
function loadImg(url){
  let oImg = document.createElement('img');
  return new Promise((resolve, reject) => {
    oImg.src = url;
    oImg.onload = () =>{
      resolve(oImg);
    }
    oImg.onerror = () => {
      reject(new Error('图片加载失败');
    }
  })
}

扩展知识:

// 回调地狱
$.ajax.get(url, function (data){
  $.ajax.get(url2, function (data2){
    $.ajax.get(url3, function (data3){
    })
  })
})
// Promise
axios().then().then()

12、前端常⽤异步场景有哪些?

参考答案:

以下2种情况必须使⽤异步
⽹络请求 ajax
 $.ajax(url, function (data){ console.log(data) })

定时任务 setTimeout setInterval

13、请描述 event loop的机制,可画图

参考答案:

console.log('start')

setTimeout(() => {
  console.log('timeout')
}, 5000)

console.log('end')

Event Loop 事件循环、事件轮询

同步代码执⾏完,启动 event loop 机制
Event Loop 到回调队列中找有没有要执⾏的代码
如果有,放⼊调⽤栈执⾏
如果没有,Event Loop会⼀直轮询

setTimeout、setInterval、ajax、DOM事件都是基于 event loop 实现的


示例:下载地址

    目录导航