老生常谈: const let var
闭包是函数作用域为了摆脱 全局作用域带来的影响。
有了ES2015我们可以使用块级作用域来解决全局作用域带来的影响。
for 有两层作用域 这两个分别有自己的作用域。
for (let i = 0; i < 3; i++) {
// console.log(i);
let i = 99999
console.log(i)
}
解析:
let i = 0;
if (i < 3) {
console.log(i)
}
i ++
const 和 let 的区别 const只声明了只读特性。
const 声明必须赋值。
const 不允许修改它指向的内存地址。但是可以修改他的属性。
最佳实践: 不用var 主用const 配合let.
总结
const 配合let 可以让我们知道我们声明的变量是可读写的。还是只读的。减少不可预测的结果。
数组的解构
当结构提取的成员小于要结构的数据时,会从左到解构出来。
当结构提取的成员大于要结构的数据时,多余的会返回undefind.类似于为定义了没有赋值的变量。
const arr = [ 100, 200, 300 ];
const [a, ...res] = arr;
console.log(a, res)
// 100 [ 200, 300 ]
// 赋默认值。
const [a, , , d=2 ] = arr;
console.log(d)
对象的解构
根据健匹配值。
const obj = {name: 'zce', age: 18};
const name = 'yoom';
// 如果结构出现同名可以起个别名。 也可以添加默认值。
const { name: objName = "123" } = obj;
console.log(objName, name)
模版字符串的高级用法
const res = console.log `打印`
输出 : [ '打印' ];
const name = 'tom';
const gender = 'true'
function myTagFunc (val, name, gender) {
console.log(val, name, gender) // 输出: [ 'hey, ', ' is a ', '' ] 'tom' 'true'
// 返回值等于res的值。
return val[0] + name+ val[1] + gender + val[2]
}
const res = myTagFunc`hey, ${name} is a ${gender}`
console.log(res) // hey, tom is a true
扩展方法:
const message = `Error: foo is not defind.`
console.log(message.startsWith('')) // 判断字符串一某某开头 返回布尔值 true
console.log(message.endsWith('。')) // 判断字符串一某某结尾 返回布尔值 false
console.log(message.includes('foo')) // 字符串包含某某 返回布尔值 true
默认值参数
带有默认值的参数 需要放在参数最后面。
剩余参数
在es2015之前js接收剩余参数使用arguments接收。
之前:
function foo () {
console.log(arguments) // [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
}
foo(1,2,3,4);
es2015:
function foo (first, ...args) {
console.log(first, args) // 1 [ 2, 3, 4 ]
}
foo(1,2,3,4);
彻底弄懂箭头函数
箭头函数表达式的语法比函数表达式更简洁, 它并没有自己的this, arguments super 或new target. 箭头函数表达式更适用于哪些本来需要匿名函数的对方。并且它不能用作构造函数。
高级语法:
// 加括号的函数体返回对象的字面量
params => ({foo: bar}) ;
// 支持剩余参数和默认参数。 参数支持解构。
没有单独的this.
在箭头函数出现之前。每一个新函数根据它是被如何调用的来定义这个函数的this值。
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this.当前作用域当中的this, 任何方式都没有办法改变它的this.
while 阻断主进程谁也执行不了,等我执行完才行。
对象字面量的增强
const bar = '345';
const obj = {
foo: 123,
// 定义的变量和名字一致的话可以这样简写
bar,
// 函数名一样 的话或者匿名也可以简写。
method1() {
console.log(this, 888)
}
// 如果这个属性名是个变量的话 可以加方括号写。
[Math.random()]: 123;
}
console.log(obj);
obj.method1()
Object.assign 扩展方法
Object.assign 是深拷贝吗?????
const source1 = {
a: 123,
b: 123
}
const source2 = {
a: 789,
d: 789
}
const target = {
a: 456,
c: 456
}
// Object.assign() 右边的对象合并到左边,如果两个对象有相同的健,则右边替换左边的值。如果右边有左边没有的话,则新加上这个属性。
const result = Object.assign(target, source1, source2)
console.log(target === result, target) // true
function func (obj) {
// 用来复制一个新的对像。
let newObj = Object.assign({}, obj)
// 在函数内部进行操作。而不改变外面的值。
newObj.name = 'func obj';
console.log(newObj, 2)
}
const obj = {name: 'global obj'};
func(obj);
console.log(obj);
Object.is 判断两个值是否相等 (感觉用处不大)
console.log(
// +0 === -0
// NaN === NaN
// 判断出NaN等于NaN
Object.is(NaN, NaN),
// 判断出+0不等于-0
Object.is(-0, +0)
)
Object.defineProperty 和 Proxy
Object.defineProperty 监听不到对象的删除操作。Proxy可以。
const person = {
name: 'zce',
age: 20
};
// 第一个参数没目标代理函数。第二个参数是个对象其中又一个监听删除 deleteProperty方法。并且返回一个新的对象。
const personProxy = new Proxy(person, {
// 一个是代理的对象。一个是传过来的需要删除属性。 删除后原对象属性即被删除。
deleteProperty(target, property) {
console.log('delete', property);
delete target[property];
}
})
delete personProxy.age;
console.log(personProxy, person, personProxy ===person) // { name: 'zce' } { name: 'zce' } false
Proxy专门为对象做访问代理器的。对象的读写都可以监听到。
const person = {
name: 'zce',
age: 20
};
// Proxy 第一个参数是需要代理的对象。 第二个参数是一个对象。这个对象有get set deleteProperty 方法
const personProxy = new Proxy(person, {
// get方法有两个参数。一个是代理的对象。一个是传过来的属性。
// 这个属性可能有也可能没有。
get (target, property) {
// 判断如果有这个属性则返回。 没有的话返回默认值。
return property in target ? target[property] : '你要的东西我没有';
},
// set方法。有三个参数。target 代理的对象。 property:传过来的属性。这个属性可能有也可能没有。没有的话则是新添加的属性。
有的话则是更新旧属性。 里面可以做你想要的逻辑判断。
set(target, property, value){
if (property === 'age' && !Number.isInteger(value)) {
throw new TypeError(`${value} is not an int`)
}
target[property] = value
}
})
personProxy.age = true;
console.log(personProxy.name);
console.log(personProxy.a);
console.log(personProxy);
在VUE中会重写数组当中的方法。替换数组原型上的方法。从而达到监听的目的。而Proxy可以很好的监听数组的变化。
proxy 监听数组
const list = [];
// 第一个参数是个数组。
通过set监听bush的数据。
const listProxy = new Proxy(list, {
set (target, property, value) {
console.log('set', property, value,0);
target[property] = value;
return true;
}
})
listProxy.push(100)
listProxy.push(10)
set 0 100 0 // 输出 输出两边不知道为什么。
set length 1 0
set 1 10 0
set length 2 0