JS基础概念
问题1 :ES6中的class 与 ES5中function的关系
ES6 中:
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
return 'hello, I am ' + this.name;
}
}
var kevin = new Person('Kevin');
kevin.sayHello(); // hello, I am Kevin
对应到 ES5 中就是:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function () {
return 'hello, I am ' + this.name;
};
var kevin = new Person('Kevin');
kevin.sayHello(); // hello, I am Kevin
参照:
ES6 系列之 Babel 是如何编译 Class 的
https://github.com/mqyqingfeng/Blog/issues/105
问题2 :this指针在不同情况下的表现
<html>
<script>
"use strict";
function Car(make, model, year) {
debugger;
this.make = make;
this.model = model;
this.year = year;
}
const car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1.make);
const myFun = () => {
debugger;
console.log(this);
return 1;
}
myFun();
function fun01(){
debugger;
return !this;
}
fun01();
</script>
</html>
第一个case:const car1 = new Car('Eagle', 'Talon TSi', 1993);
此时的this是指向对象car1的
第二个case:myFun();
此时this指向window对象,因为这个function是箭头函数,所以this指针会被提升到window
第三个case:fun01()
如果是严格模式"use strict", this指针为undefined。 如果不是严格模式, this指针指向window对象
问题3:ES6中的set、map与weakset、weakmap区别:
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。
首先,WeakSet 的成员只能是对象,而不能是其他类型的值。
其次,WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
map类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。
map与weakmap
首先,WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。
其次,WeakMap的键名所指向的对象,不计入垃圾回收机制。
基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。一个典型应用场景是,在网页的 DOM 元素上添加数据,就可以使用WeakMap结构。当该 DOM 元素被清除,其所对应的WeakMap记录就会自动被移除。
const wm = new WeakMap();
const element = document.getElementById('example');
wm.set(element, 'some information');
wm.get(element) // "some information"
参考:https://es6.ruanyifeng.com/#docs/set-map
问题4:ES6中class的继承(extends) 与 ES5中的原型继承有何不同?
ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
正确
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}
错误
class Point { /* ... */ }
class ColorPoint extends Point {
constructor() {
}
}
let cp = new ColorPoint(); // ReferenceError
上面代码中,ColorPoint继承了父类Point,但是它的构造函数没有调用super方法,导致新建实例时报错。