RE:从0开始的前端生活
JS
_config.yml
代理和反射
所谓代理,可以类比于C的指针,对代理对象的操作也会反映到目标对象上。但代理更有意义的作用在于可以实时捕获目标对象的行为。
1
|
const proxy = new Proxy(target, handle);
|
捕获器trap
捕获器为内置,如get(), set()等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
const target = {
foo: 'bar';
};
const handle = {
get() {
return 'handle override';
}
};
const proxy = new Proxy(target, handle);
console.log(target.foo);//bar
console.log(proxy.foo);//handle override
|
捕获器参数和反射API
捕获器参数可以捕获操作的值,并借此重建并输出行为,反射API可捕获原方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
const handle = {
get(trapTarget, property, receiver) {
return trapTarget[property];
}
};
const handle = {
get() {
//console what you want
return Reflect.get(...arguments);
}
};
设置空代理
const proxy = new Proxy(target, Reflect);
|
代理撤销
使用revoke和revocable
1
2
3
4
5
6
7
|
const target = {
foo: 'bar'
};
const {proxy, revoke} = Proxy.revocable(target, Reflect);
console.log(proxy.foo);
revoke();
|
注意,revoke()是幂等的,执行一次后再执行会TyepError
代理模式
总之就是在捕获器中写一些骚操作
例如:属性验证,函数参数验证等
函数
闭包
闭包指的是那些引用了另一个函数作用域中变量的函数
据我理解,闭包可以简单认为是function套function,为什么要这样做呢?让我们想下函数执行时发生了什么
————从全局到局部创建相应的上下文
也就是说,在内部function执行时,会创建外部function的对象,即内部可以引用外部变量(他们在同一条作用域链上
私有变量
私有变量放在实例中
1
2
3
4
5
6
7
8
9
10
|
function Myobject() {
let private = 10;
this.setprivate = function(num) {
private = num;
}
this.getprivate = function() {
return private;
}
}
|
该方法将私有变量储存在实例中,各实例私有变量互不干扰。
静态私有变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
(function() {
let private = 10;
function getprivate(){
return private;
}
function setprivate(value){
private = value;
}
MyObject = function(){};
MyObject.prototype.publicMethod = function() {
return getprivate();
}
MyObject.prototype.SetPrivate = function(value) {
setprivate(value);
}
})();
let person1 = new MyObject();
let person2 = new MyObject();
console.log(person1.publicMethod());
person2.SetPrivate(1);
console.log(person1.publicMethod());
|
该方法将私有变量储存在原型上,各实例私有变量相互干扰。
ps:我看不懂qwq
模块模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
let application = function() {
//私有变量和私有函数
let components = new Array();
//初始化
components.push(new BaseComponent());
//公共接口
return {
getComponentCount(){
return components.length;
},
registerCompnent(component){
if(typeof component == 'object'){
components.push(component);
}
}
}
}();
|
模块增强模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
let application = function() {
//私有变量和私有函数
let components = new Array();
//初始化
components.push(new BaseComponent());
//创建局部变量并保存实例
let app = new BaseComponent();
//公共接口
app.getComponentCount = function() {
return components.length;
};
app.registerCompnent = function(component){
if(typeof component == 'object'){
components.push(component);
}
};
//返回实例
return app;
}();
|
模块增强模式的好处在于,可以额外添加属性或方法。
关于This
闭包中this丢失解决
箭头函数
1
2
3
4
5
6
7
8
9
|
let obj = {
count: 0,
cool: function fn() {
setTimeout(() => {
this.count++
console.log(this.count);
}, 0);
}
}
|
const self = this
1
2
3
4
5
6
7
8
9
10
11
12
|
let obj = {
count: 0,
cool: function fn() {
const self = this
setTimeout(function () {
self.count++
console.log(self.count);
}, 0);
}
}
obj.cool()
|
bind(this)
1
2
3
4
5
6
7
8
9
10
|
let obj = {
count: 0,
cool: function fn() {
setTimeout(function () {
this.count++
console.log(this.count);
}.bind(this), 0);
}
}
obj.cool()
|
期约与异步函数
期约
1
|
let p = new Promise(() => {});
|
期约的状态
- 待定 pending
- 兑现 fulfilled/resolved
- 拒绝 rejected
通过执行函数控制期约状态
1
2
3
4
5
|
let p1 = new Promise((resolve, reject) => resolve(value));
let p1 = new Promise.resolve(value);
let p2 = new Promise((resolve, reject) => reject('ErrorInformation'));
let p2 = new Promise.reject('ErrorInformation');
|
注意:Promise.resolve()是幂等的,但Promise.reject()不是,后者会将其当作错误信息。
1
2
3
|
console.log(p1 === Promise.resolve(p1));//true
console.log(Promise.reject(Promise.reject()));
//Promise { <rejected> Promise { <rejected> undefined } }
|
同步/异步执行的二元性
1
2
3
4
5
6
7
8
9
10
11
12
|
try {
throw new Error('foo';)
} catch(e) {
console.log(e);// Error: foo
}
try {
Promise.reject(new Error('bar'));
} catch(e) {
console.log(e);
}
//Uncaught (in promise) Error: bar
|
异步错误必须用异步捕获方式
一些API
Promise.prototype.then()
为期约实例添加处理程序
1
2
3
4
5
6
|
let p1 = new Promise(() => {});
p1.then(兑现状态处理函数,拒绝状态处理函数)
若无返回值,则原样后传
let p1 = Promise.resolve('foo');
let p2 = p1.then();//Promise <resolved>: foo
|
Promise.prototype.catch()
为reject状态添加处理程序,等价于调用Promise.then(null, onRejected),返回一个新的期约实例。
1
2
3
4
5
6
7
8
9
10
11
12
|
let p = Promise.reject();
let onRejected = function(e) {
setTimeout(console.log, 0, 'rejected');
}
p.catch(onRejected);
p.then(null, onRejected);
let p1 = new Promise(() => {});
let p2 = p1.catch();
setTimeout(console.log, 0, p2);//Promise <pending>
setTimeout(console.log, 0, p1);//Promise <pending>
setTimeout(console.log, 0, p1 == p2); //false
|
Promise.protype.finally()
给期约添加onFinally处理程序,其在期约转换为解决或拒绝状态时都会执行。
1
2
|
let p1 = Promise.resolve();
p1.finally(() => console.log('Finally'));
|
finally()的返回值大多数情况下表现为父期约的传递。若返回的是待定期约获知onfinally()处理程序抛出错误(显式抛出或返回拒绝期约),则会返回相应期约。
promise.all() 合成期约
promise,all()返回一个新期约,其会在一组期约全部解决完后再解决。
如果所有期约都解决,那么合成期约的解决值就是所有包含期约解决值得数组。
1
2
3
4
5
6
7
8
9
|
let p = promise.all([function1, function2]);
let p = Promise.all([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve()
]);
p.then((values) => setTimeout(console.log, 1, values));
//[ 1, 2, undefined ]
|
如果有期约拒绝,则第一个期约拒绝的reason为合成期约拒绝得reason,且不影响后续的期约。合成期约会静默处理包含期约的拒绝操作
1
2
3
4
5
6
7
|
let p = Promise.all([
Promise.reject(3),
new Promise((resolve, reject) => setTimeout(reject, 1000)),
Promise.reject(4)
]);
p.catch((reason) => setTimeout(console.log, 0, reason));
//3
|
promise.race()
返回一个包装期约,是一组期约中最先解决或拒绝的期约的镜像,其它静默处理。
1
|
let p = Promise.race([function1, function2]);
|