ES6
es6 中新增声明变量方式,在同一个作用域 全部都是唯一的 禁止重复声明
let
只能在当前块中使用。let 声明的变量;决定变量能在哪里使用;而不是 形成一个作用域
- var 声明 除了在函数中声明 在其他地方声明均是全局
- let使用注意事项
- 1 let 是块级声明(作用域为块级作用域)
- 块级作用域解决词穷问题
- 2 在当前 {} 中 let 声明的变量之前不能使用该变量 否则会出现 bug:暂时性死区
- 若在声明之前使用,会有报错can’t access lexical declaration ‘a’ before initialization
- 3 在当前 {} 中不能重复声明 let 声明的变量
- 若重复声明,会报错:redeclaration of let a1 let.
- 4 函数体中 let 不能声明形参
- 5 在同一个作用域中 let 不能声明函数名
- 6 内层 {} 声明的变量不影响外层 {} 声明的变量
- 7 var 声明的变量在提升;只要遇到 let 重名;一律报错;不允许重复,默认提升到当前 let 的块级域顶端
- 8 for 中的 let 默认 () 中 let 为父级作用域,{} 中 let为子作用域
- 1 let 是块级声明(作用域为块级作用域)
for循环特殊;执行多次所以可以形成多个块级作用域
应用 防止变量污染
// 若 let ---> var 就会发生变量污染
for (let i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i);
// let ---> 012
// var ---> 333
},15)
}
拓展:块级作用域的原理是什么?
const
- const 赋值基本类型 不可修改
const a=123;
a=999;
// 因为 a 是基本类型 则报错语句为 invalid assignment to const 'a'
- const 赋值引用类型 可以修改
// obj 赋值的是一个地址 地址指向的是对象 所以可以修改
const obj={
a:333,
}
obj.b=888;
console.log(b);
var let const 区别
- 1 var 有变量提升 可以重复命名 默认全局变量
- 2 let 形成块级作用域 没有变量提升 不能重复命名
- 3 const 是常量 赋值为基本类型时不可修改 赋值为引用类型可以修改 没有提升 不能重复命名
模板字符串
- 模板字符串的基本用法
var s1 = `abc`
- 模板字符串的优势:
var obj={ name:"意思",age:5 };
var s1 ="我叫:"+obj.name+",今年:"+obj.age+"岁。"
解构赋值
解构赋值;赋值的内容要么是对象要么是数组,其他类型会报错。
注意:需要某个值,就取某个值即可,不需全部获取。
- 解构赋值:是从对象和数组中取值的另一种方式。
对象-解构赋值
-
解开什么结构?给谁赋值?
- 1 声明变量赋值是对象下的属性
- 2 声明变量与对象下的key值一样时
- 可以使用解构赋值
-
情况一:声明变量与对象下的key值一样时
let obj = {
a: 1,
b: 2
}
// let a = obj.a;
// let b = obj.b;
// 可以等同于如下一句
let {
a,
b
} = obj;
// 生成2个变量,
// a 值来自于 obj.a
// b 值来自于 obj.b
- 情况二:声明变量与对象下的key值不一样时
var {name:title}=obj;
//生成一个变量:title,值来自于obj.name
扩展-对象属性简写
var a = 3 ;
var c = 10;
var b = {
// 以前的写法 a:a,c:c,
// es6新语法:简写属性放在最上面
a,
c,
d:666,
// 赋值函数的简写
// foo:function(){}
foo(){
// foo属性赋值为function函数
},
} ;
//b对象有一个a属性,a属性的值,来自于a变量 ,
//还有一个c属性,c属性的值来自于c变量
console.log(b); // 3 10 666 function(){}
扩展-super
-
对象中新增属性 super.xx
-
将某个属性挂在在某个属性的原型对象上
-
this 是实例对象
-
super 是原型对象 且只存在 es6 函数简写中
-
this 和 super 都是关键字 且均与函数执行有关
-
在 function 中
- this —> 触发函数的对象 obj
- super —> 触发函数的对象 的__proto__,即obj.proto
- —> super === this.proto
proto__是每个对象都有的,函数对象没有__proto,函数对象有的是prototype,函数对象创建的实例对象的__proto__= 函数.prototype
注意:对象下的函数,不能直接设置原型。若设置了原型,则会报错:Cannot set properties of undefined (setting’xxx’)
es6对象扩展有哪些?—> 面试官想要答案只有 super关键字
let name = 'aaa'
let obj = {
name:'obj_cc',
foo(){
console.log(this.name); // obj_cc
return super.name
},
// bar:function(){
// console.log(this.name);
// 报错:super keyword unexpected here
// return super.name
// }
}
var bar = obj.foo;
obj.foo();
// 对象下函数;不能直接设置原型
// 对象下的函数若要设置原型 需要使用 Object.setPrototypeOf(obj,{})
Object.setPrototypeOf(obj,{
name:'bb'
})
let res = obj.foo();
console.log(res);
验证原型的修改
// 验证一
var obj1 = {
foo:function(){
}
}
obj1.foo.prototype.name = '123'; // 可以更改
// 验证二
let obj2 = {
foo:function(){
}
}
obj2.foo.prototype.name = '3333';
// 验证三
// 对象中的简写函数,不能在对象外部 通过 prototype 修改 foo 数的原型
let obj3 = {
foo(){}
}
// bug: Cannot set properties of undefined (setting'name'
// obj3.foo.prototype.name = '4444'
扩展-Objext.assign()
- Object.assign:实现拷贝继承,对象扩展运算符
var obj1={ age:5,gender:"男" }
var obj2={ ...obj1 }
var obj3={ ...obj1 , age:10 }
// 浅拷贝 一个参;深拷贝两个参
var source={ age:18,height:170,className:"3年2班" }
//克隆一个新对象出来
var newObj=Object.assign({},source);
console.log(newObj);
var newObj2={};
Object.assign(newObj2,source);
console.log(newObj2);
- Objext.assign(参一,参二…)
- 作用:合并对象
- 将参数一之后的参数 … 合并到参数一对象中 返回合并后的对象
- 参数一 与返回值对象 是 同一个对象
let obj = {
a: 1
}
let obj1 = {
b: 1
}
var obj3 = Object.assign({}, obj, obj1);
console.log(obj3);
// 验证:返回值与参数一是同一个对象
var obj4 = Object.assign(obj, obj1);
console.log(obj4);
console.log(obj);
obj.tst = 'dfafsd'
数组-解构赋值
- 格式:let [变量名1,变量名2…] = [变量1,变量2…]
变量名和变量之间用 逗号(,) 分隔
// 解构数组 [变量,变量]
// 变量赋值即数组所对应的数据
let [x, y, z] = [789, 678, 456]
console.log(x,y,z); // 789, 678, 456
函数参数-解构赋值
- eg0
function f1(obj){
console.log(obj.age);
console.log(obj.height)
}
//等价于
function f1({ age,height }){
console.log(age);
console.log(height)
}
f1({age:5,height:180})
- eg1
function foo(option){
let {url,method,success} = option;
console.log(url,method,success); // aa dd function(){}
}
foo({
url:"aa",
method:"dd",
success:function(){}
})
- eg2
// bar 2个形参
// 参二 对象;并进行解构赋值。
function bar(test,{a,b,c}){
console.log(a,b,c); // 1 2 3
}
bar(test,{
a:'1',
b:"2",
c:'3'
})
箭头函数
- 箭头函数是匿名函数 可以有返回值
- 格式:let bar = (形参)=>{console.log(形参)}; bar(实参)
- 使用场合:匿名函数的替换
let bar = (a,b)=>{
console.log('bar run ');
console.log('形参---->',a,b);
return 1
}
console.log(bar(1,2))
let obj = {
// foo foo1 两种函数
foo:()=>{
},
foo1(){
// 是一个function函数 有this
}
}
setTimeout(()=>{
console.log('只要用匿名函数都可以更改为 箭头函数');
},5)
箭头函数的简写
- 只有一个形参时
let bar1 = res =>{
console.log('bar1 run')
}
bar1()
- 有一个形参 且有返回值时
let bar2 = res => 234;
console.log(bar2());
- 有不止1个形参时
var f=(a,b,c)=>{
console.log("abc")
}
- 返回值含有正则判断时
// function telrue(val){
// return /tel/.test(val)
// }
// 等同于
let telrul = val=>/tel/.test(val);
箭头函数的特点
-
注意
-
1、没有this,所以this使用上一层作用域中this
- ----> 不能使用 bind call apply
- ----> 不能作为构造函数 不能new实例化
-
2、没有 arguments
-
3、新增 rest 参数代替 arguments
- …rest 是rest 参数,是es6新增加的;获取所有实参。rest是数组
-
4、不可以使用
yield
命令,因此箭头函数不能用作 Generator 函数 -
…rest
let foo = (...rest) => {
console.log(rest); // [11, 23, 3, 3, 3, 4]
}
let obj = {
foo,
}
obj.foo(11, 23, 3, 3, 3, 4)
- 利用箭头函数;替代了 bind 的作用,提高了性能,程序少运行了一个bind 函数
function query() {
var that = this;
$.ajax({
success: function () {
console.log(this); // this 是 ...???
},
error: () => {
// 这里使用query 中this
console.log(that);
console.log(this);
}
})
}
- 应用:更改 setTimeout 的this指向
// 法一:利用箭头函数
setTimeout(() => {
console.log(this);
}, 1)
// 法二:利用bind方法
setTimeout(function () {
console.log(this);
// settimeout的this==window
}.bind(this), 1)
异步
异步有:回调函数、promise 、async setTimeOut setTimeInterval
所有的异步都是需要触发条件的
-
程序
- 1、同步程序
- 2、异步程序
-
“步” 写代码的顺序,从上往写的,执行顺序分同步、异步
-
从上往下执行,有序执行 —>同步程序
-
在执行时,[被跳过的程序],最后有有执行了 —>异步程序
-
小案例
// setTimeout()内部的函数相对于外部的函数是慢的
// 打印结果是 1 3 2
console.log(1);
setTimeout(function(){
// 被跳过的程序。----> 因为执行慢所以被跳过了
console.log(2);
},10000)
console.log(3);
- 程序:一段一段的。参考程序;区分同步异步。同步快 异步慢
- 如何判断程序执行的先后
第一段 script(是宏任务) 中所有同步全部执行完毕。
跳过:所有异步:
微任务 promise.then
宏任务:setTimeOut setInterval
开始执行 第一段中的 微任务 promise ,所有微任务执行完毕后、
---------------------第一段结束---------------------
--------开始下一段。第一段中的宏任务---------
第二段:执行本段中所有同步代码
跳过异步:微任务: 红任务
同步结束执行微任务,微任务结束,本段结束。。。。
----------------------------
promise
- 1、创建prmise实例对象