var let const
- var:变量
//1.可以重复声明,有预解析机制
var a = 1;
var a = 2;
//2.作用域:全局作用域和函数作用域
- let:变量
//1.同一作用域下不能重复声明,不会进行预解析(必须先声明再使用)
let a = 1;
let a = 2;//报错
//2.作用域:全局作用域和块级作用域( "{" "}"之间即为块级作用域)
- const:常量
//1.不能重复声明,不会进行预解析,必须赋值,不可修改(const保证的是指向的内存地址不可修改,因此const定义的引用类型只要指向的内存地址不改变,是可以更改引用类型的值)
const arr = [];
arr.push("holle");
console.log(arr); //["holle"]
//2.作用域:全局作用域和块级作用域
解构赋值
//对象解构赋值(遵守的规则:变量的名字必须和对象的key一致)
let obj = {
a:"a",
b:"b"
}
let {a,b} = obj; //等同于 let a = obj.a;let b = obj.b;
//数组解构赋值(数组下标位置必须一样)
let arr = ["1","2","3"]
let [a,b] = arr
//字符串解构赋值(等同数组,位置一致)
let str = "abc"
let [a,b] = str
展开运算符...
//展开运算符:可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面量对象时, 将对象表达式按key-value的方式展开
let arr1 = [1,2,3]
let arr2 = [0,...arr1,4]
consloe.log(arr2) //[0,1,2,3,4]
let obj1 = {
a:1,
b:2
}
let obj2 = {
...obj1,
c:3
}
consloe.log(obj2) //{a:1,b:2,c:3}
//实现对象的深拷贝
let obj3 = {...obj1}
obj1.a = 10
console.log(obj3.a) // 输出1
箭头函数
//箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数不能用作构造函数
function fn(param){return param} //相当于 (param)=>param
//语法1:只有一个参数时"()"可以省略 param =>param
//语法2:函数体是表达式时 (param)=>{console.log(param)}
//语法3:加括号的函数体返回对象字面量表达式 param => ({a: "a"})
//语法4:不支持arguments,可使用剩余参数接收不定参 (param,...params)=>{console.log(params)}
//语法5:箭头函数不能作为构造函数,不能new
//this指向问题:
//普通函数:this指向函数调用者,默认情况下指向window;在严格模式下的函数调用下,this指向undefined;通过call,apply,bind绑定时,指向绑定的对象。
//箭头函数:没有自己的this,默认指向定义它时所在的对象的this,即父级的this。
//例:首先,在window下定义普通函数和箭头函数
function fnA() {
console.log(this)
}
let fnB = () => {
console.log(this)
}
fnA() //window
fnB() //window
//这时两个函数this都指向window,然后我们把箭头函数定义在函数内,方便改变父级this指向
let fnD;
let fnC = function () {
console.log(this)
fnD = () => {
console.log(this)
}
}
fnC() //window
fnD() //window
//这时调用两个函数,普通函数依旧指向调用它的对象,也就是window,箭头函数fnD的this继承了它父级fnC的this。
此时,我们改变fnC的指向,通过bind函数指向body
fnC = fnC.bind(document.body)
fnC() //body
fnD() //body
//此时打印结果也证明了,箭头函数的this指向始终与其父级this指向一致
数组新增方法
ps:静态方法:定义在构造函数上的方法为静态方法;实例方法:定义在构造函数和实例上的方法。 例:
function Person() { }
Person.sayName = function () { //静态方法
console.log("sayName")
}
Person.prototype.getName = function () { //实例方法
console.log("getName")
}
var xiaoming = new Person()
xiaoming.getName()
Person.sayName()
//Array.from:将一个类数组转换为真正的数组;
//参数:arrayLike 类数组
//返回值:新数组
//使用:
var obj = { 0: "a", 2: "b", length: 2 }
var arr = Array.from(obj)
console.log(arr) // ["a", undefined]
//ps1:(类数组:有length属性,其索引为非负整数;不具有数组方法。)
//ps2:类数组转数组也可使用...展开运算符
//Array.of:将一组值转换为数组;
//参数:data1,...,dataN
//返回值:新数组
//使用:
Array.of(1, 2) // [1, 2]
//arr.find:查找数组中第一个符合条件的元素;
//参数:function 回调函数,回调接受3个参数(value,index[可选],array[可选])
//返回值:符合条件的第一个元素,没有返回undefined
//使用:
let arr = [1,2,3,4]
console.log(arr.find(item=>item==2)) //2
//arr.findIndex:查找数组中第一个符合条件的元素的下标;
//参数:function 回调函数,回调接受3个参数(value,index[可选],array[可选])
//返回值:符合条件的第一个元素的下标,没有返回-1
//使用:
let arr = [1,2,3,4]
console.log(arr.findIndex(item=>item==2)) //1
//arr.flat:数组扁平化,如果原数组有空位会跳过;
//参数:depth[可选] 要扁平的层级默认1,不管几维都转为一维可以传Infinity
//返回值:新数组
//使用:
[1, 2, [3, 4]].flat() //[1,2,3,4]
//arr.fill:用一个固定值填充数组;
//参数:value用来填充的值 start[可选]开始下标 end[可选]结束下标
//返回值:新数组
//使用:
[1, 2, 3].fill(1, 1, 2) //[1,1,3]
//arr.includes:判断数组中是否包含一个指定的值;
//参数:value用来查找的值 index[可选]开始查找的位置,负数则表示倒数位置
//返回值:Boolean
//使用:
[1, 2, 3].includes(2) // true
字符串新增方法
//str.includes:判断字符串中是否包含一个指定的值;
//参数:value用来查找的值 index[可选]开始查找的位置,负数则表示倒数位置
//返回值:Boolean
//使用:
"123".includes("2") // true
//str.startsWith:判断字符串是否已另一个字符串开始;
//参数:str 要搜索的字符串 index[可选]开始查找的位置
//返回值:Boolean
//使用:
"123".startsWith("1") // true
//str.endsWith:判断字符串是否已另一个字符串结束;
//参数:str 要搜索的字符串 length[可选]字符串长度,默认str.length
//返回值:Boolean
//使用:
"123".endsWith("1") // false
//str.repeat:重复原字符串;
//参数:count 要重复的次数,小数会取整,小于-1报错
//返回值:Boolean
//使用:
"123".endsWith("1") // false
模板字符串
//模板字符串使用反引号 (` `) 来代替普通字符串中的用双引号和单引号。用(${ })将变量括起来,特殊字符需要加(\)进行转义。
//例:
let money = 100
let str1 = "本次消费"+money+"元"
let str2 = `本次消费${money}元`
console.log(str1,str2) //本次消费100元 本次消费100元 //这两种字符串拼接方式等同
对象新增内容
//Object.is(value1,value2):判断两个值是否相等,与(===)行为一致,在其基础上增加了几处不同。如: +0不等于-0、NaN等于自身;
//参数:value1,value2为比较的数据
//返回值:Boolean
//使用:
Object.is(NaN,NaN) // true
//Object.assign(target,...sources):将可枚举属性的值从一个或多个源对象复制到目标对象,相同key的值会覆盖;
//参数:target目标对象,sources源对象
//返回值:object
//使用:
let target = {name:"张三"}
let source = {name:"李四",age:"17"}
let tar = Object.assign(target,source)
console.log(tar) // {name: "李四", age: "17"}
//Object.keys(obj):返回一个所有给定目标对象自身可枚举属性名称的数组;
//参数:obj目标对象
//返回值:Array
//使用:
Object.keys({name:"李四",age:"17"}) // ["name","age"]
//Object.values(obj):返回一个所有给定目标对象自身可枚举值的数组;
//参数:obj目标对象
//返回值:Array
//使用:
Object.keys({name:"李四",age:"17"}) // ["李四","17"]
//Object.entries(obj):返回一个所有给定目标对象自身可枚举键值对的数组;
//参数:obj目标对象
//返回值:Array
//使用:
Object.keys({name:"李四",age:"17"}) // [["name","李四"],["age","17"]]
//新增对象属性:
// 1:如果属性名和变量名一致,可以简写
let name = "张三"
let obj = {
name,
age:"17"
}
// 2:属性表达式
let key1 = "name"
let key2 = "age"
let obj = {
[key1]:"张三"
}
obj[key2] = "17"
面向对象新特性
es6推出了class关键字用来定义一个类,是构造函数的一个语法糖。class定义的类必须有一个名为constructor()的函数,如果没设就会默认添加一个,这个函数中的this指向生成的实例。class声明的类具有暂时性死区,必须先定义在使用。
\\ 书写格式
class Person { // class 类名(首字母大写约定)
constructor(name, age) { // constructor(实例化传入的参数)
this.name = name
this.age = age
}
sayName() {
console.log(`name is ${this.name}`) //方法名(){函数体} 函数直接挂载到原型上
}
static maxAge = 200 //添加静态属性 static 属性名 = 属性值 静态属性无法被实例使用
static sayMaxAge() { //添加静态方法 static 方法名(){方法体} 静态方法无法被实例调用
console.log(`maxAge is ${this.maxAge}`)
}
get _age() { //原型上不能定义属性,可以通过get和set设置
return this.age
}
set _age(value) {
this.age = value
}
}
let person = new Person("张三", "17")
person.sayName() //name is 张三
Person.sayMaxAge() //maxAge is 200
person.age = 20
console.log(person.age) //20
console.log(person) //20
//继承
class Student extends Person{ // 子类名 extends 父类名
constructor(name,age,scores){
super(name,age) //为子类生成this对象,将父类属性和方法赋值到子类this上,不调用会报错
this.scores = scores
}
sayScores(){
console.log(`scores is ${this.scores}`)
}
}
let student = new Student("李明","20","600")
student.sayName() //name is 李明
student.sayScores() //scores is 600
Student.sayMaxAge() //maxAge is 200
student.age = 30
console.log(student.age) //30
proxy
ES6中提供了proxy,proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作,必须通过这层拦截。
var proxy = new Proxy(target, handler)
- target:目标对象(可以是任何类型)
- handler:配置对象,里面定义各种代理行为
例:
let target = {
name: "张三",
age: 26,
}
let proxyTarget = new Proxy(target, {
get:function(target, key) {
return target[key]
},
set:function(target,key,value){
target[key] = value
}
})
proxyTarget.age = 20
console.log(proxyTarget.age)//20
console.log(target.age)//20
此例子中,读取和设置proxyTarget的属性会经过get跟set方法。此外handler还提供多种方法对target实现代理:
-
get(target, key, receiver):代理对象读取属性 target:目标对象 key:对象属性 receiver:代理前的proxy对象 可选参数
-
set(target, key, value, receiver):代理对象属性赋值 target:目标对象 key:对象属性 value:设置的属性值 receiver:代理前的proxy对象 可选参数
-
has(target, key):代理对象属性是否存在 target:目标对象 key:对象属性
-
deleteProperty(target, key):代理对象deleteProperty() target:目标对象 key:对象属性
-
defineProperty(target, key, desc):代理对象defineProperty() target:目标对象 key:对象属性 desc:设置的属性值和相关配置
-
construct(target, args):代理实例new命令 target:目标对象 args:构造函数的参数
-
apply(target, object, args):代理对象属性赋值 target:目标对象 object:上下文对象(this) args:参数s数组
-
getOwnPropertyDescriptor(target, key):代理对象getOwnPropertyDescriptor() target:目标对象 key:对象属性
-
getPrototypeOf(target):代理对象读取原型 target:目标对象
-
isExtensible(target):代理isExtensible() target:目标对象
-
ownKeys(target):代理对象读取属性 target:目标对象
-
preventExtensions(target):代理对象preventExtensions() target:目标对象
-
setPrototypeOf(target, proto):代理对象setPrototypeOf() target:目标对象 proto:原型