Skip to content

Instantly share code, notes, and snippets.

@lesonky
Created November 30, 2018 08:02
Show Gist options
  • Save lesonky/4caaea203429290c63cd57b48e58be53 to your computer and use it in GitHub Desktop.
Save lesonky/4caaea203429290c63cd57b48e58be53 to your computer and use it in GitHub Desktop.
面试题 #面试题

天数前端JS面试题(答案)

标签(空格分隔): 面试题


[TOC]

JS基础

es5相关

1.简述JavaScript有哪些数据类型(简单)

(基础题目,比较细节,回答不全,可以稍作提示)

字符串,数字,布尔值,null,undefined五种基本数据类型,其他的全部属于Object

追问,ES6加入了一种新的基本数据类型,是什么,有什么用(难)

(ES6种比较冷的知识,可做加分题)

ES6种加入了一种新的基本数据类型Symbol,提供一个独一无二的值,可以作为属性名,可以用来消除代码中的魔鬼数字等

ES6内部定义了一些Symbol值,用来作为内部属性名.

2.===== 有什么区别(简单)

==是不严格的相等,会做隐式类型转换,null == undefined 的结果是 true

===是严格的相等,不会做隐式类型转换,null === undefined 的结果是 false

无论是==还是===都不能用来判断 NaN (可做追问)

3.nullundefined 的区别(简单)

目前版本的JavaScript,这两个值的区别并不大.(一下的区别,回答一两点即可)

typeof 运算符得到的结果不一样,typeof null 得到object,typeof undefined 得到undefined.

null表示空,undefined表示没有初始值.

null == undefined 的结果是 true,null === undefined 的结果是 false

参考文档

4.[[1,2],[3,4],[5,6,7]] 扁平化处理(多种解法,中等)

最基础的方式,使用循环遍历实现(使用concat和apply来实现的比较好,使用for循环实现的细节把控不够)

追问:用一行代码实现,多种实现

var arr = [[1,2],[3,4],[5,6,7]];



// 使用Array的concat方法(标准方法)

var farr = [].concat.apply([],arr);



// 使用 reduce 方法实现(生僻方法,可加分)

var farr = arr.reduce(function(a,b){return a.concat(b)},[]);

// 使用ES6箭头函数写法,简化function(ES6知识点,可加分)

var farr = arr.reduce((a,b) => a.concat(b),[]);



// 使用reduceRight方法与reduce方法基本一样



// 使用ES6的 ... 运算符,告别apply(ES6知识点,可加分)

var farr = [].cancat(...arr)

5.callapply 的用法及区别(中等)

callapply都用于修改函数运行时的this指向,

区别在于call将第二个及之后的参数传给源函数,做为参数列表执行,

apply的第二个参数是一个数组,这个参数在函数运行的时候会被打开,然后作为函数参数列表

6.call,apply,bind的区别(中等)

call,apply在运行时改变this指向,调用后函数立即执行

bind返回一个代理函数,需要手动调用,该函数在运行时使用bind定义的this指向

使用bind生成的代理函数,无法再次使用call,apply,bind修改this指向(细节,加分)

7.简述闭包的概念(中等)

追问:

一下代码,控制台会输出什么,为什么?

var a = 10;

function b(){

    var a = 5;

    console.log(this.a)

    return function(){

        console.log(a)

    }

}

b()();

本题的考点为闭包

第一个console.log(this.a)中,this指向window,获取全局变量所以输出为10

第一个console.log(a)中,这里的a取的是函数定义时候的a,所以输出为5

8.关于this指向的问题,下面的代码控制台会输出什么(难)

var length = 10 

function fn(){    

    console.log(this.length);

} 

var obj = {    

    length: 5,    

    method: function(fn) {                

        fn();            

        arguments[0]();              

    } 

} 

obj.method(fn);

本题考点为this

输出结果为 10,1

第一个fn()调用时,this指向window,

第二个arguments[0]()是难点,arguments是个对象,这里相当于调用对象的方法,this指向arguments

9.立即执行函数的写法以及使用场景?(中等)

写法多种多样

// 最常用的写法

(function(){})();

// 次常用的方法

(function(){}());

// 其他方法,在函数前加上任意的位运算符,都可以导致函数表达式立即生成函数,从而实现函数立即执行

+function(){}();

10.如何深度复制一个对象(难)

JSON字符串化再解析,实现一个简单的深度复制

追问:

  • 如何解决函数的复制(难)

function的toString方法,会的到function得代码,用eval函数转换成函数

  • 如何解决原型链的复制(难)

先获取原型,再将新的对象原型设置为原来的对象的原型

11.将数组["8","13","7","5","4","21","1","6"]按照数字从小到大的顺序排列 (简单)

考点是Arraysort方法,默认是按照字符串来排序的,需要自己写一个sort的函数来实现排序

var arr = ["8","13","7","5","4","21","1","6"];

arr.sort((a,b) => a-b);  // 这里包括了一个隐式类型转换

12.写一个得到阶乘第N项的方法(难,循环,递归)

追问:

  • 用递归实现(中等)
// 简单的递归,每次都要把之前的都算一遍,效率低下,复杂度高

function factirial(n){

    if (n === 1) return 1;

    return n * factirial(n -1);

}
  • 优化递归实现(尾递归,加分)
// 尾递归实现,会被优化,但是需要一个额外参数

function factirial(n,total){

    if (n === 1) return total;

    return factirial(n-1,n*total);

}
  • 使用curry化将函数变得优雅一些(加分)
// curring简单实现,这个function很简陋,只针对当前函数,用来示意一下

function currying(fn,n){

    return function(m){

        return fn.call(this,m,n);

    }

}

function tailFactirial(n,total){

    if (n === 1) return total;

    return factirial(n-1,n*total);

}


var factirial = curring(tailFactirial,1);



// ES6参数默认值的方式,可以避免curry化

function factirial(n,total = 1){

    if (n === 1) return total;

    return factirial(n-1,n*total);

}

jQuery相关

1.简述jQuery对象与DOM对象的却别(简单)

  • jQuery对象是一个类数组对象,使用选择器获取的DOM对象都被包装成jQuery对象,通过[index]方法,可以从jQuery对象中取出原生的DOM对象

  • DOM对象可以使用原生的dom方法,jQuery对象不可以使用原生dom方法,但是可以使用更加强大的jQuery方法

  • DOM对象可以使用 $(DOM对象)的方式包装成jQuery对象

2.简述window.onload与$(document).ready的区别(简单)

  • window.onload需要在页面所有元素全部加载结束才触发,包括图片下载,而且全局只能有一个,后写的会覆盖先写的

  • $(document).ready通过多种检测,在页面dom结构完成时触发,不需要等到图片下载结束,触发速度更快,可以写多个

3.简述jQuery的事件代理机制以及使用场景(简单)

  • 通过将事件绑定到父元素上,来代理子元素事件处理,可以减少绑定次数,同时可以处理后添加的DOM元素,不需要添加新的事件绑定

4.如何手动触发DOM事件(简单)

  • 使用 trigger 方法

5.如果网页中已经使用$作为变量名,又要使用jQuery,如何避免变量名冲突(简单)

  • noConflict 方法,包括一个 true 参数,可以把 jQuery 也让出去

6.jQuery插件有哪些形式,如何创建一个jQuery插件(中等)

  • 方法插件,通过 $.extends 来扩展jQuery的静态方法

  • 原型插件,通过 $.fn.extentds 来扩展原型方法

  • 写插件的时候可以做一个noConflict处理,避免将原有同名插件覆盖掉

7.jQuery的ajax同步模式和异步模式有什么区别,如何设置(简单)

  • 同步的ajax并不建议使用,他会阻塞ajax请求,直到ajax返回,运行完回调函数才会之后的代码

  • 异步的ajax调用后会立即执行后面的代码,ajax返回之后,会执行回调函数

  • jQuery的ajax中使用async参数来设置同步或者异步

8.如何避免事件的超高频率触发(如滚动事件,键盘输入事件等)(中等)

使用节流函数来实现,实现思路是通过定时器的不断设定和取消,节流事件处理函数的运行.

ES6相关

1. ES6提供了新的变量声明方式(简单)

提供了 letconst 两种变量声明方式

追问:

  • 与var的区别(中等,细节继续追问)

letconst属于块及作用域,var是函数及作用域,letconst声明的变量不能够重复声明

  • 临时死区的概念(中等)

在作用域块中 letconst声明的变量,从块开始,到声明语句之间的地带,叫临时死区,在临时死区中,虽然不存在变量提升,但是如果使用了声明的变量,就会报错

  • 对全局变量的影响(细节)

var 如果在全局中使用,会在全局挂载一个变量,如果原来有同名变量,则覆盖原来的变量,letconst在全局中使用,不会覆盖全局变量,只是遮盖他们

2. 箭头函数与普通函数的区别(中等)

追问:

  • 箭头函数中this的指向

箭头函数没有自己的this,在箭头函数中使用this调用的是外层的this

  • 箭头函数中arguments是否可用

箭头函数中没有arguments变量,如果在一个普通函数内部使用,arguments指向外层函数的arguments

3.for...in...循环与for...of...循环的区别(难,细节)

for...in...用于遍历对象的属性,当遍历数组时,会把挂载在数组上的其他属性也遍历出来,遍历数组的键

for...of...用于遍历数组,只遍历数组元素,不遍历数组上的其他属性,遍历数组的值

对于普通的对象for...of...结构不能直接只用,必须部署Iterator接口,但是for...in...循环依然可以遍历键名

参考文档

ES6 标准入门(第二版)P180

4....操作有哪些用处(中等)

  • 可以用来打开数组,做数组的合并,代替apply方法

  • 可以用来打开对象,做对象合并

  • 可以用来设置rest参数

  • 可以用来打开任何有Iteritor接口的对象

5.函数参数默认值的用法(难)

追问: 下面的代码,控制台依次输出什么?

function a({a,b} = {a:1,b:2}){

    console.log(a);

    console.log(b);

}

function b({a=1,b=2}){

    console.log(a);

    console.log(b);

}

function c({a=1,b=2} = {a:1,b:2}){

    console.log(a);

    console.log(b);

}

a();   // 1,2

a({a:2});  // 2,undefind

a({a:2,b:3}); // 2,3

b(); // 报错

b({a:2}); // 2,2

b({a:2,b:3}); // 2,3

c(); // 1,2

c({a:2}); // 2,2

c({a:2,b:3}); // 2,3

6.数组去重(使用es6的方式)(中等)

let arr = ["1","2","1","3","2"];

let dArray = Array.from(new Set(arr));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment