总结一下前端常见javascript基础面试题:

1.var ,let 和const的区别:

let和const是es6新增的语法, let和var都可以定义变量,但是二者作用域不同,let有块级作用域,var没有。所以在var变量值会存在变量提升现在,而let不会;const是定义常量。

2.typeof返回类型:

区分值类型和引用类型;

值类型: Number,String,Boolean,Undefined,Symbol

引用类型:Object,function,null(typeof null === 'object')

所以typeof的返回值为 Number,String,Boolean,Undefined,Symbol Object,function。常见的强制类型转换parseInt,parseFloat,toString。常见的隐式类型转换:拼接字符串, == ,等等;

3.数组slice和splice区别:

slice: slice(startIndex, endIndex),如果传入一个参数,默认从startIndex剪切到endIndex = (arr.lenght-1);

splice: splice(startIndex, number, string),和slice类似,但是只限于类似。第一个参数是起始位置,第二个参数是需要剪切的数量,第三个参数是你需要插入数组中的内容。也可以设置第二个参数为0,不剪切数据,直接插入数据,和数组的常用方法(push, pop,unshift,shift)联系起来。

两者最大的区别就是slice是纯函数,splice是非纯函数;

4.[10, 20, 30].map(parseInt)输出内容是什么?

[10, 20, 30].map(parseInt) 等价于[10, 20, 30].map( (item, index) => { return parseInt(item, index)});所以问题等价于返回的数组中的值是什么?parseInt(10, 0) = 10; parseInt(20, 1) = NaN; parseInt(30, 2) = NaN;

5.get请求和post请求之间的区别?

1.get一般请求url地址查询,post一般提交表单操作;

2.get参数拼接在url上,受url长度限制;post请求放在请求体内,所以post请求数据体积可以较大;

3.安全性: post易于防止CSRF攻击(cross-site request forgery跨站伪请求,伪造你的信息,向服务器发送请求,窃取账号密码);

6.call, apply, bind的区别?

三者都是改变函数this的指向,call和apply只是参数传递有区别:call(this, a1, a2, a3, ...), apply(this, argument) argument是数组或者伪数组(或者说是集合);call和bind的区别:bind返回一个函数对象;

7.事件的委托(代理):

事件的委托(代理)是通过事件的冒泡实现的,事件的冒泡可以理解为由下向上触发父级元素事件的一个过程(气泡会受到浮力,从下往上运动)。给父级元素绑定事件,可以通过子元素来触发,这就是事件委托(代理)。

8.函数闭包和闭包的特性,有何负面影响?

函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。(MDN官方介绍 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures)

闭包的特性:函数作为参数或者返回值。闭包会占用内存,得不到释放。(自由变量的查找是在函数定义的地方,而不是函数使用的地方)。

9.阻止事件冒泡和默认行为的方法?

阻止冒泡:event.stoppropagation;阻止默认行为:event.preventdefault;

10.如何减少DOM操作?

1.缓存DOM的查询结果

2.多次DOM操作合并到一次(Fragment)

11.函数声明和函数表达式的区别?

函数表达式:const fn = function () { };函数声明:function fn () { };两者的区别就是函数表达式会预解析(页面加载时会提前解析函数声明,函数声明写在逻辑后面,也会执行生效),而函数表达式不会。

12.new Object( )和Object.creat( )区别?

new Object( ) === { };我们习惯于 const obj = { }这中写法,其实这种写法等于 const obj = new Object ( )。new Object ( )的原型指向于Object.prototype,即obj.__proto__ === Object.prototype。Object.creat(null)是没有原型的(Object.prototype.__proto__  === null),但是Object.creat({ })可以指定原型。

例如:const obj1 = { }; const obj2 = Object.creat(obj1);  obj2.__proto__ === obj1

13.关于this:

this指向其实就是作用域和调用对象的问题。

14.手写字符串trim方法:

trim是去除字符串开头或结尾处的空格的方法。例如 const  str = '  hello  '; console.log(str.trim()) = 'hello';

为了保证兼容性,我们可以使用正则表达式的方式改写trim方法:

String.prototype.trim_ =function(str) {

    return str.replace(/^\s+/, '').replace(/\s+$/, '');

}

(^表示开头,\s表示空格,+表示一个或多个,$表示结尾)

15.求数组中的最大值

方法有多种:

1.简单暴力:直接调用Api。Math.max()

2.利用数组的sort()方法,然后去最后一位数。(sort()方法是用来排序的,按从小到大的顺序),arr.sort([...])[arr.length - 1]

3.利用forEach循环,(map也行,但是map返回值是默认是数组,所以如return的值要修改)

const arr = [];

let max =arr[0];

arr.forEach( item => max = max < item ? max = item :max)

4.利用for循环:

const arr = [];

let max =arr[0];

for (let i =0; i < arr.length; i ++) {

max < arr[i] ? max = arr[i] : max

}

5.冒泡算法

16.如何实现继承?

ES6中新增的class方法,extends和super关键字就可以实现继承。ES5可以通过prototype实现继承。

17.如何捕获js程序中的异常?

1.手动捕获异常:try{ },catch{ },finally{ }方法。一般会在异步调用的时候用到。(promise函数。promise函数是同步,then方法才是异步)

2.自动捕获异常:通过window.onerror = function(message,source,lineNum,colNum,error) { } (对于跨域的js,如cdn,没有详细的报错原因;对于压缩的js,还要配合sourcemap反查到未压缩的行、列)。

18.获取当前页面url参数

有两种方式:

1.这里需要用到bom中location的一个api:location.search(BOM: location, navigator, screen,history)。通过location.search我们可以拿到url的参数(包括问号,所以需要用substr方法进行修改)。

function getUrl() {

const str =location.search.substring(1);//拿到问号后面的字符串。例如:?id=666&&name=zhangsan => //id=666&&name=zhangsan

    const value = str.split('&&').map( item => {/*map是纯函数方法,返回一个数组,如果用forEach会显示undefined,因为forEach没有返回值 */

            const arr = item.split('=');//把=切割,返回一个数组,包含两个元素

                const key = arr[0];//把数组的第一项复制给key

                const value = arr[1];//把数组的第二项赋值给value

            return { key, value }

        })

}

2.第二种是直接使用URLSearchParams

function getUrl(url) {

const str =location.search;

    const paras =new URLSearchParams(str);//URLSearchParams是一个class构造函数

    paras.get(url)

}

3.使用正则表达式

19.数组排平(flatten)比如:[1, 2, 5, [1, 2, 5], 7] 变成[1, 2, 5, 1, 2, 5, 7],[1, [2, 3, 4], [1, [ 2, 3, [ 4, 5] ] ], 6] = [ 1, 2, 4, 5, 1, 2, 3, 4, 5, 6]

首先这个问题肯定涉及到数组合并的问题,concat()方法是肯定需要使用的。Array.prototype.concat.apply([ ], arr)这句代码的意思就是合并arr数组里面的数组,但是只会合并两层(例如:Array.prototype.concat.apply([ ], [1, [2, 3])  === [1, 2, 3])Array.prototype.concat.apply([ ], arr)其实可以写成 [ ].concat(arr)

const arr = [1, 2, 4, [2, 4, 5, [1, 2, [4]]]];

function flatten(arr) {

    let res =Array.prototype.concat.apply([], arr)

    const flag = arr.some(item => iteminstanceof Array)//some( ) 返回一个Boolean值

    if (flag) {

        return flatten(res)//如果i数组中还嵌套数组,递归

}

    return arr;

}

console.log(flatten(arr));// [1, 2, 4, 2, 4, 5, 1, 2, 4]

20.数组去重

1.使用Set( )函数:

function unique1(arr) {

    const set =new Set(arr);

    return [...set]//ES6结构赋值

}

2.遍历数组(性能上有所欠缺,需要多次遍历,indexOf本质也是遍历)

function unique2(arr) {

    const res = [];

    arr.forEach( item => {

        if (res.indexOf(item) <0) {

        res.push(item)

        }

    })

        return res;

}

21.数组排序(升序,降序)

1.使用Array.prototype.sort( )方法。sort()排序规则是按照UTF-16编码排序。sort( )中可以传入函数作为参数。

   升序:arr.sort((a, b) => a - b);降序:arr.sort((a, b) => b - a);

2.冒泡算法。冒泡算法就是将数组元素中相邻的两个元素的值大小做比较,交换顺序。

    for (let i =0; i < arr.length; i ++ ) {

        for (let j =0; j < arr.length - 1 - i; i ++) {

            if (arr1[j] >arr1[j +1]) {

                let temp =arr1[j];

                arr1[j] =arr1[j +1];

                arr1[j +1] = temp;

               }

        }

    }

22.手写深拷贝

涉及到多层次的对象和数组就需要递归

function deepClone(obj) {

    let res;

    if (typeof obj ==="object" || obj ==null) { //判断传入参数的类型

        return obj;

    }

    if (obj instanceof Array) { //是数组则赋值为数组

    res = [];

    }    else {

        res = { } //否则赋值为对象

    }

    for (let keyin obj) {

        if (obj.hasOwnProperty(key)) {//这个是为了代码严谨。obj上可能会有原型的key。不写不太影响结果

            res[key] =deepClone(obj[key]);//递归

        }

}

    return res;

}

22.函数节流防抖

1.函数防抖:

function debounce(fn, delay) {

    let timer;

    return function () {

        if (timer) {

            clearTimeout(timer);

        }

    timer =setTimeout(function () {

        fn.apply(this, arguments)

        })

        timer =null;

    }

}

2.函数节流:

function throttle(fn, delay) {

     let timer =null;

    return function () {

        if (timer) {

        return;

        }

    timer =setTimeout(function () {

        fn.apply(this, arguments)

        }, delay);

        timer =null;

    }

}

23.Promise函数和异步

Promise是ES6中新增的函数。主要是解决callback hell(回调地狱)。Promise((resolve,rejecte)=> {})三种状态:pending(将要进行)、fulfilled(完成)、rejecte(失败)。同时还衍生了generator函数,async await(解决then()回调问题)。Promise函数体是同步,then()方法是异步。then( () => { } )接受成功的回调函数,catch(() => { })接受失败后的回调。 

24.Cookie、session、Localstorage、Sessionstorage的区别和作用

Cookie中的数据存储在客户端,session中的数据存储在服务器端。所以从安全性上考虑,用户的登陆信息需要存储在session当中。cookie中仅保存一些非安全性的信息,比如用户登陆状态过期的时间,如果不设置用户登陆状态过期时间,默认页面关闭,登陆状态也就消失。

Localstorage是把数据存储在浏览器本地的一种存储方式。如果用户不手动清除数据信息,则数据不会消失。Sessionstorage则是仅保存当前页面的数据信息。当前页面关闭,则数据信息自动清除。

在存储大小方面。cookie的存储容量为4kb左右,session为4mb。

25.地址栏输url会发生什么?

1.第一步是查看本地缓存

2.第二步是域名DNS解析

3.第三部是建立TCP链接

4.第四步是发起HTTP请求

5.浏览器接收到服务器返回的文件,渲染

26.TCP/IP模型

TCP/IP是一系列网络协议的总称。这些协议的目的是使得计算机之间可以进行信息交换。

TCP/IP模型四层架构从上到下分别是链路层、网络层、传输层、应用层

1.链路层的作用是负责建立电路连接,是整个网络的物理基础,典型的协议包括以太网、ADSL等。

2.网络层负责分配地址和传送二进制数据,主要要协议是IP协议

3.传输层负责传送文本数据,主要协议是TCP

4.应用层负责传送各种最终形态的数据,是直接与用户信息打交道的层,主要写是HTTP、ftp等

你可能感兴趣的:(总结一下前端常见javascript基础面试题:)