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等