let和const
1.var声明的变量挂载在window上,而let和const声明的变量不会;
var a = 4;
console.log(a) //4
console.log(window.a); //4
const a = 4;
console.log(a) //4
console.log(window.a); //undefined
let a = 4;
console.log(a) //4
console.log(window.a); //ubdefined
2 .var声明的变量存在变量提升;let和const不存在变量提升;
console.log(a);//undefined a已经声明,但还没有赋值,默认得到undefined
var a = 10;
console.log(b);//报错,b is not defined 找不到
let b = 4;
console.log(c);//报错,c is not defined 找不到
const c = 100;
3.let 和const 声明形成块级作用域
function fn() {
var a = 100;
console.log(a); //100
}
fn()
4。在同一作用域下;let和const不能声明同名变量,而var 可以;
var a = 10;
var a = 20;
console.log(a);//20
let b = 10;
let b = 20;
console.log(b);//报错 标识符b已经被声明;
5.暂时死区
let和const命令声明的变量无变量提升;且都会被所在声明的代码块中;在let和const
// 命令执行前,使用该变量都会报错,这一部分被称为暂时性死区;
var a = 123;
if(true) {
a = 'abc';
let a;
}
6.const
一旦声明必须赋值,不能使用null占位;
声明后不能再修改
如果声明的是复合数据类性,可以修改其属性
const a =100; //声明必须赋值
const list = [];
list[0] = 10;
console.log(list); //10
const obj = {a:100};
obj.name = 'apple';
obj.a = 10000; //复合数据类型,属性被修改
console.log(obj); {a:10000,name:apple};
7,在let声明之前,typeof运算符是百分百安全的,不会抛出错误;
console.log(typeof a) ; //undefined
在以前没有let和const命令的时候,typeof是一个安全的运算符,
即使变量没有被声明,也会正常返回undefined,但如果typeof处在死区中, 处理了在后文被let和const的变量,将会报错。
var a = 123;
typeof undeclared_variable;
if(true) {
// 暂时性死区
typeof a;
let a
console.log(a)
}
Proxy
在vue3.0中将会通过Proxy来替换原来的 Object.defineProperty 来实现数据库响应式,
Proxy是ES6中新增的功能, 用于修改某些操作做的默认行为;等同于在语言层面作出修改;所以属于一种“元编程”;即:对语言编程进行编程; Proxy可以理解为: 在目标对象之前架设一层‘拦截’;外界对该对象的访问,都必须先通过这层拦截; 因此提供了一层机制,可以对外界的访问进行过滤和改写, Proxy意思为代理;代理某些操作,或者也可以叫为"代理器";
1.arget代表要添加代理的对象;
2handel 用来自定义对象中的操作;比如可以用来自定义set或者get函数;
3.obj:是被代理完成之后返回的对象;
当外界每次对obj进行操作时,就会执行handel对象上的一些方法
let p = new Proxy(target,handel,obj);
Proxy有以下几种方法:
1.get(target, propKey, receiver
get()方法: 用于拦截某个属性的读取操作;可以接受三个参数,1:目标对象;2属性名,实例本身(操作行为所针对的对象)3:可选;
var person = {
name: '张大帅'
};
var proxy = new Proxy(person, {
get: function (target, property) {
if (property in target) {
return target[property];
}else {
throw new ReferenceError('抛出错误')
}
}
})
console.log(proxy.name);
//如果没有get方法拦截,则返回undefined;有则抛出错误;
console.log(proxy.age)
2. set(target, propKey, value, receiver)
set()方法: 用来拦截某个属性的赋值操作,可以接收4个参数; 1;目标对象,2属性名,属性值,Proxy实例本身;4:可选;
const obj = {
'name': 'null'
};
// <!-- 设置该对象的属性不可写 -->
Object.defineProperty(obj, 'name', {
writable: false
});
const handler = {
set: function (obj, prop, value, receiver) {
Reflect.set(obj, prop, value);
}
};
const proxy = new Proxy(obj, handler);
proxy.name = '我是空智';
console.log(proxy.name); // 打印的是 null
3. has(target, propKey)
has()方法:该方法是判断某个目标对象是否有该属性的姓名;接受两个参数;1.目标对象,2属性名,;返回的是一个布尔值;
4. construct(target, args)
construct()方法:用来拦截new命令的;接受三个参数:1目标对象,2构造函数的参数对象及创造实例的对象;3可选,用来拦截对象属性;
5.apply(target, object, args)
apply()该方法用来拦截函数的调用,接受三个参数:1目标对象,2目标上下文this对象;3目标对象的数组
下面是 Proxy 支持的拦截操作一览,一共 13 种。
get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。 set(target, propKey,lue, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值;deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。 defineProperty(target,propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。 setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object,...args)、proxy.apply(...)。
construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
Proxy有许多用途,包括运算符重载,对象模拟,简洁而灵活的API创建,对象变化事件,甚至Vue 3背后的内部响应系统提供动力。
数据响应式
Proxy可以完美的监听到任何方式的数据改变;唯一缺陷可能就是浏览器的兼容性不好了
let str = (obj,setBind,getLogger) => {
let handel ={
get(target,perty,receiver) {
getLogger(target,perty);
return Reflect.get(target,perty,receiver)
},
set(target,perty,value,receiver) {
setBind(value,perty)
return Reflect.set(target,perty,value);
}
}
return new Proxy(obj,handel)
}
let obj = {age:21};
let q = str(
obj,
(v,perty) => {
console.log(`监听到属性${perty}改变为${v}`)
},
(target,perty) => {
console.log(`'${perty}' = ${target[perty]}`)
}
)
q.a = 2;
console.log(q.a)