JS面试题

1. 数据类型

  • number
  • string
  • boolean
  • symbol
  • null
  • undefined
  • object

2. string方法

  • string.substr
string.substr(start,length) // 若length不写则延续到最后
  • string.substring
string.substring(start,end) // 哪个小就把哪个看作start

2. promise怎么用

  • 生成promise
function(){
  return new Promise(function(resolve,reject){
    if(成功){
      resolve()
    }else{
      reject()
    }
  })
}
  • then
$.ajax(...).then(成功函数,失败函数)
  • then是链式的
$.ajax(...).then(成功函数1,失败函数1).then(成功函数2,失败函数2)
//ajax返回404,失败函数1执行,成功函数2执行

3. 手写ajax

let request = new XMLHttpRequest();
request.open('POST','/xxx');
request.onreadystatechange = ()=>{
  if(request.readyState === 4 && request.status === 200){
    var value = JSON.parse(request.responseText);
  }
}
// 是post才用在send里写东西,不然可以直接send()
request.send('a=1&b=2');

4. 手写闭包

function createAdder(){
  let n=1;
  return function(){
    n+=1;
    console.log('n', n)
  }
}

let adder = createAdder();
adder()  //n===2
adder()  //n===3
console.log(n)  //n is not defined

5. this是什么

  1. fn()里面的this正常模式下是Window
  2. a.b.c.fn()里面的this就是a.b.c
  3. new F()里面的this就是F()对象
  4. () => {console.log(this)}里面的this就是外面的this

6. 立即执行函数

!function(){}()
作用是创造一个函数作用域,防止污染全局变量
es6新语法可以代替立即执行函数

{
  let name = 'p'  //用let声明变量即可
}

7. async/await语法

async init() {
  this.loading = true
  const { getImgTaskNumber, getCountByStatus } = this.$api.task
  const promises = []
  for (const index in this.imageData) {
    const promise = getImgTaskNumber(this.imageData[index].name)
    promises.push(promise)
    const info = await promise
    this.imageData[index]['taskCounts'] = info.count
    this.imageData[index]['time'] = info.overdue
  }
  let promise = getCountByStatus('unallocated')
  promises.push(promise)
  this.imgDetected = await promise
  promise = getCountByStatus('labeling')
  this.labeling = await promise
  promises.push(promise)
  await Promise.all(promises)
  this.loading = false
}

8. 深拷贝

  1. 用JSON深拷贝
let a = {...}
let b = JSON.parse(JSON.stringify(a))

但这个方法不支持函数、引用、undefined、正则...

  1. 递归拷贝
let china = {
  nation : '中国',
  birthplaces:['北京','上海','广州'],
  skincolor :'yellow',
  friends:['sk','ls']
}
//深复制,要想达到深复制就需要用递归
function deepCopy(o, c){
  let copy = c || {}
  for(let i in o){
    if(typeof o[i] === 'object'){  //要考虑深复制问题了
      if(o[i].constructor === Array){
      //这是数组
        copy[i] =[]
      }else{
      //这是对象
        copy[i] = {}
      }
      deepCopy(o[i],copy[i])
    }else{
      copy[i] = o[i]
    }
  }
  return copy
}
let result = {name:'result'}
result = deepCopy(china,result)
console.dir(result)

9. 数组去重

  1. ES5(计数排序的逻辑)

    function distinct(a) {
      let obj = {}
      let result = []
      a.forEach(value => {
        if (!obj[value]) {
          obj[value] = 1
          result.push(value)
          }
        })
      return result
    }
    let a = [1,1,1,1,2,3,4,5,6,5,3,2,4,56,56,4,1,2,7]
    let b = distinct(a)
    console.log(b)
    
  2. ES6

    function distinct2(array){
     return Array.from(new Set(array));
    }
    distinct2([1,1,2,3]) //[1,2,3]
    

10. 用正则实现string.trim()

function trim(string){
  return string.replace(/^\s+|\s+$/g,'') 
  //^\s+表示开头有一个或多个空格,|表示或,\s+$表示结尾
}

11. 什么是原型

数组的push方法就是原型里的,数组是个对象,每个对象都有一个隐藏属性__proto__,而数组的'proto'指向数组的原型Array.prototype,push方法就存在这里面可以直接引用(还有pop,slice,splice也是)

原型链

12. class(类)

  1. 类的声明不会提升
  2. 举例
class Rectangle {
    // constructor
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }
    // Getter
    get area() {
        return this.calcArea()
    }
    // Method
    calcArea() {
        return this.height * this.width;
    }
}
const square = new Rectangle(10, 10);

console.log(square.area);
// 100
  1. extends(继承)
class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak1() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  constructor(name, gender) {
    super(name)
    this.gender = gender
  }
  speak2() {
    console.log(this.name + ' barks. ' + this.gender);
  }
}

var d = new Dog('Mitzie', 'man');
d.speak2();

13. JS如何实现继承

  1. extends(ES6)
    上面的extends
  2. 原型链(ES5)
function Animal(){
  this.body = '肉体'  //自身属性
}
Animal.prototype.move = function(){}  

function Human(name){
  Animal.apply(this,arguments)  //继承Animal的自身属性
  this.name = name
}

Human.prototype.__proto__ = Animal.prototype

Human.prototype.useTools = function(){}  
//Human自己的原型属性

14. 实现一个延时的同步函数

function execTime(t){
  let start = Date.now();
  //let start = new Date().getTime()
  //let start = + new Date();
  while(Date.now() - start < t){}
}

console.log(1)
execTime(3000)
console.log(2)

15. 实现异步函数

function execTime(t,callback){
  setTimeout(callback,t)
}

console.log(1)
execTime(3000,function(){
  console.log(3)
})
console.log(2)

16. 数组方法的使用

<h1>我要学 <span class="text">__</span></h1>
<ul class="box">
    <li>Java<input type="checkbox" value="Java"></li>
    <li>前端<input type="checkbox" value="前端"></li>
    <li>PHP<input type="checkbox" value="PHP"></li>
</ul>
<div>
    <input type="text" class="ipt"><button class="add">添加</button>
</div>
let box  = document.querySelector('.box')
let text = document.querySelector('.text')
let addBtn = document.querySelector('.add')
let input = document.querySelector('.ipt')

box.onclick = function (){
    text.innerText = [...box.querySelectorAll('input')].filter(checkbox=>checkbox.checked)
        .map(checkbox=>checkbox.value)
        .join(',')
}

addBtn.onclick = function () {
    let node = document.createElement('li')
    let checkbox = document.createElement('input')
    node.innerText = input.value
    checkbox.type = 'checkbox'
    checkbox.value = input.value
    node.appendChild(checkbox)
    box.appendChild(node)
}

17. 阻止事件冒泡

<h1>你选择的是 <span class="text"></span></h1>
<button class="btn">点我</button>
<ul class="box">
    <li>菜单一</li>
    <li>菜单二</li>
    <li>菜单三</li>
</ul>
let box  = document.querySelector('.box')
let text = document.querySelector('.text')
let button = document.querySelector('.btn')
let input = document.querySelector('.ipt')


button.onclick = function (e) {
    box.style.display = 'block'
    e.stopPropagation()
}

document.onclick = function () {
    box.style.display = 'none'
}

box.onclick = function (e) {
    e.stopPropagation()
    text.innerText = e.target.innerText
}

18. 面试题,按属性分组

一个数组里有很多项(对象),每一项都有label属性,把所有label相同的项分为一个数组

function x(arr){
  let t = {}
  for(let i=0;i<arr.length;i++){
    if(t[arr[i].label]){
      t[arr[i].label].push(arr[i])
    }else{
      t[arr[i].label] = []
      t[arr[i].label].push(arr[i])
    }
  }
  return t
}

19. Array.sort面试题

排序

let l=[2,3,1]
l.sort()  //[1,2,3]

let a = [{age:3},{age:1},{age:2}]
a.sort(function(x,y){
  return x.age-y.age
})

20. Array.reduce

let a = [1,2,3]
a.reduce(function(sum,n){
  return sum+n  //6
},0)

第一个参数是一个函数,第二个参数是初始值传给sum,会遍历这个数组,n就是数组里的每一项,sum就是上一次return的数据

  • 面试题
    将一个数组里的所有小数组合并成一个大数组
let a = [[1,2,3],[4,5,6]]
a.reduce(function(sum,n){
  n.forEach(function(value,key){
    sum.push(value)
  })
  return sum
},[])

21. replace

let s = 'ad{{ra}}ds{{rd}}d'

function replaceTemp(s,object){
  for(let x in object){
    s = s.replace('{{'+x+'}}',object[x])
  }
  return s
}

replaceTemp(s,{ra:11, rd:12})

22. blur、focus事件不能冒泡

23. 判断是不是数组

a instanceof Array
Array.isArray(a)

24. 将伪数组转化为数组

let a = {0:'a',1:'b',length:2}
let b = Array.from(a)
//或者Array.prototype.slice.call(a)

25. 鼠标滑过出现浮层

onmouseover然后display: block,滑的快慢可以设置setTimeout,用e.offsetTop可以检测元素距离顶部的位置

26. 面经

27. 函数面试题

  1. 满足fn() === fn/fn.fn === fn
function fn(){
  fn.fn=fn;
  return fn
}
  1. 满足obj.obj.obj...... === obj
obj = {}
obj.obj = obj

obj.obj.obj.obj.obj === obj  //true

27. 数组API

  • 面试题一

let students = [
{name:'1',score:86},
{name:'2',score:86},
{name:'3',score:86},
{name:'4',score:86},
]
用数组API计算总分、平均分、最高分、最低分

//总分
students.map(s=>s.score).reduce((s,n)=>s+n,0)
//平均分
students.map(s=>s.score).reduce((s,n)=>s+n,0)/students.length
//最高分
students.map(s=>s.score).sort()[student.length-1]
//最低分
students.map(s=>s.score).sort()[0]
  • 面试题二(sort)
    用sort对学生的姓名按字典序排序
let students = [{name: 'c'},{name: 'b'},{name: 'a'}]

stundents.sort((x,y)=>{
  if(x.name < y.name) {
    return -1
  }
  if(x.name > y.name) {
    return 1
  }
  return 0
})

28. Object面试题

  • 面试题1
let obj ={a:1,b:2,c:3}
//实现select函数,select(obj, ['a', 'c'])
//输出 {a: 1, c: 3}
function select(obj,arr) {
    let n = {}
    arr.forEach(function(value){
        n[value] = obj[value]
    })
    return n
}

function select2(obj,arr) {
  let a = arr.reduce((o,n)=>{
    o[n]=obj[n]
    return o
  },{})
  return a
}

function select3(obj, arr) {
  return arr.reduce((ret, key) => 
    Object.assign(ret, { [key]: obj[key] }), {})
}


select(obj, ['a', 'c'])
//输出 {a: 1, c: 3}
  • 面试题2

let p1 = {
'姓名': 'jirengu',
'性别': '男',
'年纪': 4,
}
写一个函数,实现把p1变成
<dl><dt>姓名</dt><dd>jirengu</dd><dt>性别</dt><dd>男</dd><dt>年纪</dt><dd>4</dd></dl>

  1. 方法一
function renderTpl(p) {
    let html = '<dl>'
    for(let key in p){
        html += '<dt>' + key + '</dt>' + '<dd>'+ p[key] +'</dd>'
    }
    html += '</dl>'
    return html
}
  1. 方法二(Object.keys)
function renderTpl(p){
    return '<dl>'+ Object.keys(p).reduce((html,key)=>`${html}<dt>${key}</dt><dd>${p[key]}</dd>`,'') +'</dl>'
}
  1. 方法三(Object.entries)
function renderTpl(p){
    return '<dl>'+ Object.entries(p).reduce((html,key)=>`${html}<dt>${key[0]}</dt><dd>${key[1]}</dd>`,'') +'</dl>'
}
  • 面试题3
  1. 有学生列表,label代表每个学生的特点,假设每个学生的特点是唯一的,写一个函数将学生按特点分类
let sundents = [{name: 'a', label: 'happy'}, {name: 'b', label: 'angry'}]
function mapper(students){
  let object = {}
  students.forEach(value=>{
    object[value.label] = value
  })
  return object
}
  1. 若学生的特点不是唯一,写函数将学生按特点分组
function mapped2(students) {
  let object = {}
  students.forEach((value)=>{
    if(!object[value.label]){
      object[value.label] = []
    } 
    object[value.label].push(value)
  })
  return object
}
  • 面试题4
    写一个函数,可以判断两个对象的值是否相等
function isObjectValueEqual(a, b) {
    var aProps = Object.getOwnPropertyNames(a);
    var bProps = Object.getOwnPropertyNames(b);

    if (aProps.length != bProps.length) {
        return false;
    }
    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i];
        if (a[propName] !== b[propName]) {
            return false;
        }
    }
    return true;
}

29. 写函数去掉开头的'$$'

let a = {$$x: 1, y: 2, z: [{$$a: 3. b: 4}]}
//把a转为json"{"a":1,"b":2,"c":3}"

//判断开头的方法
str.substring(0,2) === '$$'

//函数,这个方法牛逼
const toJson = obj => {
  return JSON.stringify(obj, (key, n) => {
    if(key.substring(0,2) !== '$$'){
      return n
    }
  })
}
// n第一次是obj,接下来就是上一次return的东西,,然后这个函数会遍历上一次return的东西

30. 正则面试题

用正则匹配以135或136或137开头的11位手机号码
/^13[567]\d{8}$/

31. 写出输出的内容

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

推荐阅读更多精彩内容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,028评论 0 2
  • 如何控制alert中的换行?\n alert(“p\np”); 请编写一个JavaScript函数 parseQu...
    heyunqiang99阅读 1,083评论 0 6
  • 这位刚来不久的阿姨做事真的特别很上心特别勤快,每一件事情都做的特别仔细,看到地上就主动去扫,每次撤台都会先把垃圾清...
    words2阅读 579评论 0 1
  • 关于生活关于活法!只愿意活的很认真很认真,不计较的一点都无所谓,该计较的必计较的一尘不染,原谅这放荡不羁爱自由的赤...
    纵情嬉戏天地间阅读 143评论 0 1
  • 年轻时冲动是一种美好的果断 但一定要听取中肯的意见 年轻时傲气是一种自信的气质 但一定不可以傲视的忽略 年轻时单纯...
    涤生_7687阅读 379评论 4 3