JavaScript ES6基础
1.let声明
- 1.let不像var有变量声明提升,未声明直接使用会报错
console.log(a); //undefined
var a;
console.log(b); //报错
let b;
- 2.在ES5中,全局变量是挂载在顶层对象(浏览器是window)中。而let不会
var a = 1;
console.log(window.a); //1
let b = 2;
console.log(window.b); //undefined
- 3.在ES6之前,我们都是用var来声明变量,而且JS只有函数作用域和全局作用域,没有块级作用域,所以{}限定不了var声明变量的访问范围。而let可以声明块级作用域的变量。
if(true){
var num = 10;
}
console.log(num); //10 var定义的变量没有块级作用域
if(true){
let num2 = 10;
}
console.log(num2); //报错 num2 is not defined
- 4.let变量不能重复声明,而var声明的变量可以
let num = 10;
let num = 11;
console.log(num); //报错 Identifier 'num' has already been declared
var num = 10;
var num = 11;
console.log(num); //11 var可以重复声明
- 5.let 配合for循环的独特应用
<ul id="ul1">
<li>11111</li>
<li>222222</li>
<li>333333</li>
<li>444444</li>
</ul>
window.onload = function(){
var allLis = document.getElementsByTagName("li");
for(var i=0;i<allLis.length;i++){
allLis[i].onclick = function(){
console.log(i);
}
}
//无论点击哪个元素都是输出4
for(let j=0;i<allLis.length;j++){
allLis[j].onclick = function(){
console.log(j);
}
}
}
//依次点击各个li元素分别输出0/1/2/3
2.模版字符串
- 由来:传统的方式拼接字符串和变量时,如果拼接内容很多的话,会变得很复杂。需要大量的双引号 +号 变量名组合在一起,很不方便,极易出错
- 用法:用反引号(tab顶上那个键)标识将模版包裹起来。${}里面既可以放变量,也可以放函数,还可以放表达式
<script>
var str = "我是谁,我在哪"
var n = 16
document.body.innerHTML += `<h1>${str}?你就少说两句吧</h1>`
document.body.innerHTML += `<h1>2的16次方=${Math.pow(2,n)}</h1>`
</script>
运行结果:
<h1>我是谁,我在哪?你就少说两句吧</h1>
<h1>2的16次方=65536</h1>
- 另外,eval(string) 函数可计算某个字符串,并执行其中的的 JavaScript 代码。string为要计算的 JavaScript 表达式或要执行的语句
<script>
let n=3,m=4
let codeStr = "console.log(123)"
eval(codeStr)
let codeStr2 = "n+m"
let s = eval(codeStr2) //对于表达式,会自动返回计算的结果
console.log(s)
</script>
控制台打印:
123
7
3.解构赋值
- 含义:按照一定的模式从数组或者对象中取值,对变量进行赋值的过程称为解构
- 数组:定义变量时,将变量放入左边的数组中,将自动与右边的数组元素进行匹配赋值(通过下标)
<script>
var arr = [0,1,2]
//传统赋值
var a=arr[0],b=arr[1],c=arr[2]
console.log(a,b,c) //0 1 2
//解构赋值
var [d,e,f] = arr
console.log(d,e,f) //0 1 2
//实例 交换数值
var g = 1,h = 2;//这里不能少 分号
[g,h] = [h,g]
console.log(g,h) // 2 1
</script>
- 对象:定义变量时,将变量放入左边的对象中,将自动与右边的对象进行匹配赋值(通过属性名称)
<script>
var p = {name:"张三",age:20,friend:"李四"};
//传统赋值
var name=p.name,age=p.age
console.log(name,age); //张三 20
//解构赋值
var {name,age} = p;
console.log(name,age); //张三 20
</script>
- 字符串:定义变量时,将变量放入左边的数组中,将自动与右边的字符串素进行匹配赋值(通过下标)
<script>
var str = "hello world"
var [a,b,c] = str
console.log(a) //h
console.log(b) //e
console.log(c) //l
</script>
- 解构赋值允许使用默认值:如果右边的对应的值为undefined,则使用默认的值
<script>
// 如果右边的对应的值为undefined,则使用默认的值
var {name="张三",age=20} = {}
console.log(name,age) //张三 20
// 右边有值则正常赋值
var {name="张三",age=20} = {name:"李四",age:25}
console.log(name,age) //李四 25
//数组
var [num1=10,num2=20] = []
console.log(num1,num2) //10 20
var [num1=10,num2=20] = [5,15]
console.log(num1,num2) //5 15
</script>
4.扩展运算符
- 将一个数组转为用逗号分隔的参数序列
<script>
// 将所有传参求和
function sum(){
var total = 0
for(var i = 0; i < arguments.length; i++){
total += arguments[i]
}
return total
}
var arr = [1,2,3,4,5]
var arr2 = [3,4,5]
console.log(sum(...arr)) //15
console.log(sum(...arr2)) // 12
// ES5 使用apply()将参数以数组的形式传入
console.log(sum.apply(window,arr)) //15
</script>
- 还可以用于数组的拼接与合并
<script>
// 数组拼接
var arr = [1,2,3]
var arr2 = [3,4,5]
arr.push(...arr2)
console.log(arr) // [1, 2, 3, 3, 4, 5]
// 数组合并
var arr3 = [1,2,3]
var arr4 = [3,4,5]
var newArr = [...arr3,...arr4]
console.log(newArr) // [1, 2, 3, 3, 4, 5]
</script>
- 对象
<script>
//复制键值对给新的对象
var p = {name: 'kyo',age: 20}
var p2 = {...p}
console.log(p2.name,p2.age) // 'kyo' 20
//修改新对象对旧的对象无影响
p2.age = 25
console.log(p) //{name: "kyo", age: 20}
//对象拼接
var fnobj = {
test:function(){},
test2:function(){}
}
var fnobj2 = {
test3:function(){},
test4:function(){}
}
var methods = {...fnobj,...fnobj2}
console.log(methods)//{test: ƒ, test2: ƒ, test3: ƒ, test4: ƒ}
// ES5方法 循环遍历添加
Object.keys(p).forEach(key => {
p2[key] = p[key]
})
</script>
- 字符串:直接转换成单个字符组成的数组
<script>
var str = 'hello'
var arr = [...str]
console.log(arr) // ['h','e','l','l','o']
// ES5方法
arr = str.split('')
</script>
5.Set 数据结构
- 含义:ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
- 常用方法:
| 方法名 | 说明 |
|---|---|
| new Set() | 创建Set |
| add() | 向Set中添加元素 |
| delete() | 从Set中删除目标元素 |
| has() | 判断某元素是否存在 |
| clear() | 清空所有元素 |
- 基本使用
<script>
// 创建Set
var mySet = new Set()
// 添加元素(一次只能添加一个)
mySet.add(1)
mySet.add(2)
mySet.add(3)
console.log(mySet) //Set(3) {1, 2, 3}
// size属性
console.log(mySet.size) //3
// 删除元素
mySet.delete(2)
console.log(mySet) //Set(2) {1, 3}
// 判断是否拥有指定元素
mySet.add([7,8]) //添加引用类型的元素
console.log(mySet.has(1)) //true
console.log(mySet.has(2)) //false
console.log(mySet.has([7,8])) //false 不是同一个 指针,这里要注意
//清空元素
mySet.clear()
console.log(mySet) //Set(0) {}
</script>
- Set和Array可以互转,可以利用它进行数组去重
<script>
var arr = [1,2,3,4,2]
// Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化
var mySet = new Set(arr)
console.log(mySet) //Set(4) {1, 2, 3, 4} 去重
// set转数组
var newArr = Array.from(mySet)
console.log(newArr) //[1, 2, 3, 4]
</script>
- Set可以使用forEach遍历
<script>
var mySet = new Set([1,2,3,4])
mySet.forEach(function(val,index){
// Set集合的键名和键值一样的
console.log(val,index)
// 1 1
// 2 2
// 3 3
// 4 4
})
</script>
6.可选链操作符(Optional Chaining Operator)
- 由来:当对象多级嵌套时,某个属性可能是空值(null或者undefined),强制读取就会报错
- 解决方法:读取对象之前,在 "." 添加 "?" 避开报错(为空值则不继续执行,直接返回undefined)
<script>
var p1 = {
name: "kyo",age: 20,
friend: {
name: "Daimon",age: 25,
}
}
//p2没有friend,更没有friend.name
var p2 = {
name: "kyo",age: 20,
}
console.log(p1.name)
console.log(p1.friend.name)
console.log(p2.name)
console.log(p2.friend?.name)
//报错
console.log(p2.friend.name)
</script>
- 兼容性:现代浏览器(Chrome 80+、Firefox 74+、Safari 13.1+)和 Node.js 14+ 均支持
7.JavaScript 代理
-
由来:
有时候我们需要监控或拦截对一个对象的操作——比如读取属性、赋值、删除等,并在这些操作发生时执行自定义逻辑(如校验、日志、响应式更新等)。为此,ES6 引入了 Proxy(代理)机制:它能创建一个目标对象的代理,从而在不修改原对象的前提下,拦截并自定义其基本行为。
-
Proxy 是一个构造函数,接收两个参数
- target:要被代理的目标对象(原始数据源,只能是对象、数组,不能不能直接代理基本类型);
- handler:一个配置对象,它的属性是一些陷阱函数(trap functions),用于定义代理在各种操作下的行为。
对 proxy 的操作,最终会作用到 target 上;
proxy 和 target 是双向绑定的——通过代理修改属性,原对象也会变;直接改原对象,代理读取时也会反映出来(但不会触发 handler 中的拦截)。
const p = new Proxy(target, handler)
-
基本用法:通过 handler 中的陷阱方法,可以监听对象的各种操作。常见陷阱包括:
- get(target, prop):读取属性时触发
- set(target, prop, value):设置属性时触发
- deleteProperty(target, prop):删除属性时触发
-
示例代码
<script>
//配置项
var handler = {
//读取时触发
//第一个参数就是target,也就是包装的目标对象
//第二个参数数访问的属性值
get(obj, prop) {
console.log('get执行')
return obj[prop]
},
//修改时触发
set: function (obj, prop, value){
console.log('set执行')
obj[prop] = value
},
//删除属性时触发
deleteProperty(obj, prop){
console.log('deleteProperty执行')
}
}
const p = new Proxy({}, handler)
//赋值触发set
p.name = "张三"
//读取触发get
console.log(p.name)
//删除触发deleteProperty
delete p.name
</script>
在 set 和 deleteProperty 中,必须手动操作 obj,否则属性不会真正改变;
在严格模式下,set 和 deleteProperty 必须返回 true/false,否则会报错;
直接操作原始 target 对象(绕过 proxy)不会触发任何拦截。
Proxy 不是“复制”对象,而是给对象套上一层“监听壳”
- 浏览器兼容性
![]()
8.Fetch
- 作用:用更现代、更简洁、基于 Promise 的方式替代 XHR(XMLHttpRequest),让异步请求更好写、更好组合、更符合 JavaScript 的发展趋势
- 基本语法:传入url,用then获取返回数据
fetch('http://127.0.0.1:8097/api/data.json').then(res=>{
console.log(res)
})

- 第二个参数,对象类型,有以下常用字段
| 字段 | 说明 |
|---|---|
| body | 请求参数,附带在请求体中 |
| headers | 请求头 |
| method | 请求的方法,比如 "GET"、"POST",默认值是 "GET" |
| mode | 指定请求的模式,默认cors,表示允许跨源请求,same-origin表示只允许同源请求,这里js层面允许,能不能拿到数据还得看后端的接口设置 |
- 返回值:返回一个 Promise,resolve 时回传 Response 对象,Response.body 是 ReadableStream(可读流)数据,可以对其进行转换
async getMsg(){
//发请求获取响应
const response = await fetch('http://127.0.0.1:8097/api/data.json')
//转换数据为json
const json_data = await response.json()
console.log(json_data)
}
- Fetch 想解决 XHR 的几个痛点:
| XHR 的问题 | Fetch 的改进 |
|---|---|
| 回调地狱(onreadystatechange) | 基于 Promise,天然支持 async/await |
| API 设计老旧、冗长 | 语法简洁,链式调用清晰 |
| 配置分散(open + setRequestHeader + send) | 一次性传入配置对象 |
不是为了“功能更强”,而是为了“写起来更舒服、更现代化”
- Fetch 和 XHR 的核心区别
| 对比维度 | XMLHttpRequest (XHR) | Fetch |
|---|---|---|
| 出现时间 | 1999 年(IE5) | 2015 年(ES6 时代) |
| 编程范式 | 回调(Callback) | Promise(支持 async/await) |
| 默认行为 | 自动发送 cookie(同域) | 默认不带 cookie(需手动设 credentials: 'include') |
| 错误处理 | 只有网络失败才触发 onerror;HTTP 404/500 仍算“成功” | 同样:只有网络故障才 reject;404/500 仍 resolve(需手动检查 response.ok) |
| 取消请求 | 支持 xhr.abort() | 原生不支持,需配合 AbortController |
| 浏览器兼容 | 所有浏览器(包括 IE) | 现代浏览器(IE 不支持) |
| 上传/下载进度 | 支持 onprogress | 原生不支持(需读取 response.body 流手动处理) |
Fetch所谓404/500 仍算“成功”:指的是不会被trycatch的错误捕获
不支持超时设置(需自己用 AbortController + setTimeout 实现)
Fetch它简化了“写法”,没简化“HTTP 本身”


浙公网安备 33010602011771号