1、es6新特性
- let和const关键字
- 箭头函数
- 多行字符串
- 解构赋值
- Promises
let声明变量和const声明常量;
变量不能重复声明;都是块级作用域;不存在变量提升;
箭头函数:es6提供了简洁的箭头函数语法,可以更简单的定义函数,还可以帮我们更好地处理this关键字,所以我们使用箭头函数的时候,要关注this的作用域;
模板字符串:es6引入了模板字符串语法,可以方便的进行字符串的差值和多行字符串的定义;
// 基本使用
var str = `这是一个字符串模板写法`;
// 变量解析:${变量}
var num = `ES6`;
var str = `这是一个${num}字符串模板写法`;
Promise:可以解决回调地狱的问题用来处理异步代码;
Promise实例存在以下方法:
1、then()是实例状态发生改变事的回调函数
2、catch()用于指定发生错误时的回调函数
3、
Promise构造函数存在以下方法:
1、all()
2、race()
3、
rest 参数(剩余参数)
// es5
function date() {
console.log(arguments);
}
date('白芷', '阿娇', '思慧');
// es6
// 用于获取函数剩余的参数
// 形式:(…变量名),把一个分离的参数序列整合为一个数组,值是一个数组。
// 只要不知道传入函数的参数个数,就可以使用
function func(...args){
console.log(args);
}
func(1,2,3,4,5,6) // [1, 2, 3, 4, 5, 6]
解构赋值:es6提供了解构赋值的语法,可以简化代码,并帮助获取对象的一些属性值;
// 解构数组
var arr = [1,3,4,6];
var [a,b,c] = arr;
console.log(a,b,c); // 1 3 4
// 函数中可以通过解构数组返回多个结果
function fn(a,b){
return [a+b,a-b,a*b,a/b];
}
var [r1,r2,r3,r4] = fn(8,4);
console.log(r1,r2,r3,r4); // 12 4 32 2
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。用来对一个对象进行拷贝;
数组新增的一些方法
// foeEach、map、filter、some、every、indexOf、find、includes等等
set和map的区别
Map是键值对,Set是值的集合,键和值可以是任何值;
新的循环语句:es6提供了for…of和fot…in两种新的循环语句,可以更方便的对对象和数组进行遍历;
1、for of无法循环遍历对象:会报错
2、遍历输出结果不同:for in循环遍历的是数组的键值(索引),而for of循环遍历的是数组的值
3、新定义属性输出结果不同:新定义的属性也会被for in输出来了,而for of并不会对新定义的属性进行输出。
...展开运算符(扩展运算符):可以将数组或者对象里面的值展开,还可以将多个值收集为一个变量;
模块:es6引入了模块系统,可以方便的将代码分成几个独立的模块,以便于维护和重用,它还可以帮助我们管理代码的依赖关系;
异步编程:es6提供了async和await两个关键字,可以简化异步编程,可以帮助我们编写更简洁、更易读的代码;
类:es6提供了类的语法,可以方便的定义对象的构造函数和方法,可以帮助我们更好的组织代码,并方便的复制对象;
用ES6新增数组函数修改引用类型的元素里面的属性原数组也会跟着改变。
如果你不希望原数组被改变解决办法:
对操作数组进行深拷贝。用拷贝的对象调用数组处理方法,原数组就不会改变了。
2、什么是深拷贝、什么是浅拷贝?
深拷贝就是即使变量的值相同,但是变量指向的内存地址不相同,互相独立。
这里b是a的深拷贝
var a = {name: "a"}
var b = JSON.parse(JSON.stringify(a));
console.log(a, b); // {name: "a"} {name: "a"}
b.name = "b";
console.log(a, b); // {name: "a"} {name: "b"}
浅拷贝就是尽管他们的变量名不相同,但是他们指向的内存地址相同,互相影响。
这里b就是a的浅拷贝。
var a = {name: "a"}
var b = a;
console.log(a, b); // {name: "a"} {name: "a"}
b.name = "b";
console.log(a, b); // {name: "b"} {name: "b"}
// 这里注意一点, 这里直接修改b这个变量,系统会将b的指针指向常量区存有4的内存地址
// 而不是将b之前指向a的内存地址里的值改为4
b = 4;
console.log(a, b); // {name: "b"} 4
3、什么是函数防抖和节流?
防抖函数:指连续触发事件但在设定时间内只执行最后一次触发事件的函数。(核心:从新开始)单位时间内,频繁触发事件,只执行最后一次;
应用场景:搜索框搜索输入、文本编辑器实时保存
const debounce = (fn, time) = {
let timeout = null;
return function {
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, time);
}
};
节流函数:指连续触发事件但在设定时间内只执行一次触发事件的函数。(核心:不要打断我)
单位时间内,频繁触发事件,只执行一次;
应用场景:高频事件(例如:快速点击、鼠标滑动、resize事件(是在浏览器窗口大小发生变化时触发)、scroll事件)、下拉加载、视频播放记录时间
代码实现思路:利用定时器
const throttle = (fn, time) => {
let flag = true;
return function() {
if(!flag) return;
flag = false;
setTimeout(() => {
fn.apply(this, arguments);
flag = true;
}, time);
}
}
4、普通函数的this和箭头函数的this有什么区别?
普通函数中的this:
(1)方法中的this,指向调用这个方法的对象
(2)在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window;
(3)在严格模式下,没有直接调用者的函数中的this是 undefined;
(4)使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象。
箭头函数中的this:
(1)箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值,自己本身并没有this值;
(2)箭头函数的this永远指向其上下文的this,任何方法都改变不了其指向,如call(), bind(), apply()。
普通函数和箭头函数的区别:普通函数的this指向是动态的,它取决于函数的调用方式并且可以使用call、apply、bind改变this的指向,箭头函数的this指向是固定的,指向定义时上层作用域中的this,箭头函数没有自己的this,call、apply、bind无法改变箭头函数的指向,全局作用域下箭头函数的this指向全局对象,箭头函数不可以当做构造函数,不能使用new运算符,否则会报错,箭头函数的函数体内不可以使用arguments,super,new.target,箭头函数不可以使用yield命令,不能用作Generator函数;在class中使用箭头函数,其js会和类实例进行绑定;
5、cookie、localstorage和sessionStorage的区别?
三者都是在客户端存储数据的方式。
(1)cookie存储数据的大小为 4kb 左右;localStorage和sessionStorage存储数据的大小在不同浏览器都会有所不同,但是一般都比cookie要大得多;
(2)cookie只能存储字符串类型的数据;localStorage和sessionStorage可以存储js中的任意数据类型;(字符串、数值、布尔值、对象以及数组等等)
(3)cookie可以设置数据的过期时间,一旦过期则会被浏览器删除;localStorage是永久存储,sessionStorage是会话存储,数据会一直保存在客户端,直到被手动删除或者浏览器缓存被清除;
(4)存储的作用域:cookie的存储范围是在整个域名下,也就是说在同一个域名下的所有页面吗都可以共享cookie中的数据;需要长期存储一些数据就用localStorage;需要在当前会话中临时存储一些数据使用sessionStorage;如果存储敏感信息时要加密处理
6、js垃圾回收机制
7、JavaScript运行机制
JS是单线程的
8、var、let和const的区别?
var 和 let 用以声明变量,const 用于声明只读的常量;
var 声明的变量,不存在块级作用域,在全局范围内都有效,let 和 const 声明的,只在它所在的代码块内有效;
let 和 const 不存在像 var 那样的 “变量提升” 现象,所以 var 定义变量可以先使用,后声明,而 let 和 const 只可先声明,后使用;
let 声明的变量存在暂时性死区,即只要块级作用域中存在 let,那么它所声明的变量就绑定了这个区域,不再受外部的影响;
let 不允许在相同作用域内,重复声明同一个变量;
const 在声明时必须初始化赋值,一旦声明,其声明的值就不允许改变,更不允许重复声明;
9、什么是promise和async-await?
10、JS事件循环
console.log('同步代码1');
setTimeout(() => {
console.log('setTimeout')
}, 0)
new Promise((resolve) => {
console.log('同步代码2')
resolve()
}).then(() => {
console.log('promise.then')
})
console.log('同步代码3');
// 最终输出"同步代码1"、"同步代码2"、"同步代码3"、"promise.then"、"setTimeout"
(1)setTimeout 回调和 promise.then 都是异步执行的,将在所有同步代码之后执行;
(2)虽然 promise.then 写在后面,但是执行顺序却比 setTimeout 优先,因为它是微任务;
(3)new Promise 是同步执行的,promise.then 里面的回调才是异步的。
11、什么是跨域?常见的跨域方式有哪些?
跨域指:当A网站访问B网站时,由于协议、域名、端口的不同,会使浏览器开启自我防护机制同源策略。
浏览器的同源策略是指:js脚本在未经允许的情况下,不能够访问其他域下的内容。
JSONP方式:动态创建一个script标签,利用外链脚本的方式,去实现跨域请求。
CORS方式:是跨域资源的一种共享方式,是一种实现跨域请求数据的一种技术。
正向代理:首先搭建一个代理服务器,用户发送请求到代理服务器上,代理服务器就发送请求到真正的服务器上,然后服务器将数据返回到代理服务器,代理服务器再将数据返回给用户。
反向代理方式:指用户发送请求到反向代理服务器,反向代理服务器再将请求发送到真正的服务器上
12、call、apply、bind方法的区别?
(1)c执行方式不同:
call和apply是改变后页面加载之后就立即执行,是同步代码。
bind是异步代码,改变后不会立即执行;而是返回一个新的函数。
(2)传参方式不同:
call和bind传参是一个一个逐一传入,不能使用剩余参数的方式传参。
apply可以使用数组的方式传入的,只要是数组方式就可以使用剩余参数的方式传入。
13、js 检测变量类型
var num = 10
// 判断变量类型
console.log(typeof num) // number
var str = 'Hello' // string
var flag = true // boolean
var ud = undefined // undefined
var n = null // object
// prompt取过来的值是字符串
var age = prompt('请输入你的年龄') // string
// js 变量转字符串类型
var num = 5
num = num.toString()
console.log(num, typeof(num)) // 5 , string
num = num.String()
console.log(num, typeof(num)) // 5 , string
var s = null
// s = s.toString() // 报错
s = s.String()
console.log(typeof(s)) // string
// 对象转换为字符串 // JSON.stringify(obj)
const obj = {
id: 0,
name: '张三',
age: 12
}
const objToStr = JSON.stringify(obj)
console.log('obj:', obj)
// obj: {id: 0, name: '张三', age: 12}
console.log('objToStr:', objToStr)
// objToStr: {"id":0,"name":"张三","age":12}
// 字符串转换为对象
var str = '{"name":"小明","age":18}';
var json = JSON.parse(str);//第一种
var json2 = eval("(" + str + ")");//第二种
var json3 = (new Function("return " + str))();//第三种
14、什么是懒加载和预加载?
都是进行页面的性能优化、减少页面的加载时间。
懒加载:指在页面滚动时,按需加载页面上的图片、视频或者其他资源,当页面加载时,只会加载页面的初始内容,而不会加载页面上的所有资源,所以当用户去滚动页面的时候,再依据需要去加载对应的资源。可以减少页面的加载时间,提高用户体验。
预加载:指在页面加载时,提前加载页面上的资源,以便在用户需要时可立即访问,一般来说,通过页面中的头部标签,去使用外部 <link> 标签,外链样式以及 <script> 外部js方式去实现。提高了响应速度和体验