目录
JS复习
属性标志
属性值默认为true,一般情况下下面三个是不会出现的
Object.defineProperties方法可以用来一次定义多个属性
Object.getOwnPropertyDescriptors方法是一次获得所有的属性描述符
对象的访问器属性
对象有两种属性,一种是数据属性,另一种是访问器属性,之前使用的一直是数据属性
访问器属性由getter和setter方法表示,在对象字面量中,他们用get和set表示
访问器属性的设计思想是不以函数的方式调用,而是正常读取,getter在幕后运行
let user = {
name : 'mu',
lastname : 'ge',
get fullname() {
return `${
this.name} ${
this.lastname}`;
}
}
alert(user.fullname)//mu ge
get是只有在存在其他属性的时候才可以用,set是在给对象属性值赋值时会用的,就像下面的例子
let user = {
name : 'mu',
lastname : 'ge',
get fullname() {
return `${
this.name} ${
this.lastname}`;
},
set fullname(value) {
[this.name, this.lastname] = value.split(' ');
}
}
user.fullname = 'xiao li';
console.log(user.name);//xaio
console.log(user.lastname);//li
这样也相当于创建了一个虚拟的属性
访问器属性没有value和writeable
一个属性只能是两种属性中的一种,不能两种都是
如果直接用getter和setter创建一个新的属性,比如说创建一个age属性,然后在外部给age赋值会存在obj._age中(当然,在get中返回中也应该是this._age)
大众约定,以下划线开头的属性是内部属性,不应该从对象外部进行访问
继承的六种方法
- __proto__和[[prototype]]不一样
__proto__是[[prototype]]的getter/setter
[[Prototype]]只能是对象或者null
prototype是对象的一个常规属性,[[prototype]]是表示实例对象继承自那个对象
![](/qrcode.jpg)
__proto__只是Object.prototype的访问器属性,所以obj.__proto__被读取或者赋值,然后对应的getter/setter会被从原型中调出,然后改变[[prototype]]
__proto__只是一种访问[[prototype]]的方式
更改原型是一个非常缓慢的操作,因为破坏了对象属性访问操作的内部优化,因此,要避免使用
__proto__不能作为键使用,会报错
1.构造函数式继承
function Father() {
}
function Son() {
Father.call(this);//就是直接把父函数引入
}
就是直接在子函数中用call引入父函数
这是工业开发中会用的一种方法,完全囊括了父函数
缺点:不能继承借用构造函数的原型,每次构造函数都要多走一个函数
2.原型链式继承
function Father() {
}
function Son() {
}
Son.prototype = new Father();
就是简单的原型链继承,这是最原始的一种方法,缺点:会继承过多的不必要的属性
3.组合继承(原型链 + 构造函数)(不建议)
这种方法虽然弥补了前两种方法的各自的一点小问题,但是,前两种方法最大的问题并没有解决,使用构造函数继承继承父函数里面的内容,也可以传参,使用原型链继承弥补用构造函数不能继承父函数原型链上面的内容的缺点,但是还是会继承过多的不必要的属性
4.原型式继承
本质是浅拷贝,可以直接用这个方法来实现,就是Object.creat();括号里面传想继承的对象
其实还是原型链继承
5.寄生式继承
就是把原型式再次封装,然后在对象上面扩展新方法,再返回新对象
function create(obj) {
let clone = Object.create(obj);
// 这里可以给clone加新方法
return clone;
}
let father = {
};
let son = create(father);//这样son也继承了create里面的新方法,也继承了父对象的属性
6.寄生组合式继承(最常用)
是class的实现原理,为了解决多new父构造函数的缺点
function Father() {
}
function Son() {
}
Son.prototype = Object.create(Father.prototype);//最重要的
参考这个
https://blog.csdn.net/S_aitama/article/details/108757445?spm=1001.2014.3001.5501
考核总结
- 关于同步异步
setTimeout(()=>{
console.log('timeout');
},0);
new Promise((resolve) => {
console.log('a');
setTimeout(()=>{
console.log('c');
}, 0);
resolve();
console.log('b');
}).then(() =>{
console.log('promise');
}).catch(() =>{
console.log('error');
});
console.log('code');
错误答案:
code a b timeout promise c
正确答案:
a b code promise timeout c
这是为什么呢?
原因是promise在被new的时候也是在最开始的同步执行里面的,只有进入到resolve或者reject函数中的时候才会进入微队列,其他时候都按照异步执行的规则进行
- 调库版数组去重,array本身的方法好香啊
let arr = [1, 2, 3, 4, 1, 1, 1, 3, 4, 5, 6];
let arr2 = arr.filter((element, index, arr) => {
return arr.indexOf(element) === index;
})
-
关于prototype和__proto__,constructor之间的关系,以Person构造函数为例
Person构造函数构造的实例对象都有prototype原型,prototype原型中有constructor属性指向Person构造函数,__protot__是实例对象访问prototype的一个方法 -
关于var,let,const
var只是没有块级作用域而已,并不是完全没有作用域
let出来的属性不会加入window(这样会更加规范,也是创造let解决的一个小问题) -
事件只有取消冒泡的才会被捕获
-
继承类的constructor必须调用super(…),并且一定要用在使用this之前