本篇主要记录一些关于函数、类、箭头函数、继承、构造函数等相关的一些问答
Q: 函数声明和函数表达式的定义和区别
A:
1
2
3
4
|
// 表达式
const fn = () => {};
// 声明
function fn() {}
|
区别在于声明会存在提升(hoisting)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
console.log(fn) // 报错, 暂时性死区, 如果改成var来定义, 将打印undefined
const fn = () => {}
console.log(fn1) //fn1(){} OK 因为函数声明存在提升(hoisting)
function fn1(){}
//另外注意一点,如果存在表达式
if(true){
fn2(){
return 2
}
}else{
fn2(){
return 1
}
}
// 这里因为提升关系, fn2会返回1, 通过表达式可以解决
let fn2;
if(true){
fn2 = () => { return 2}
}else{
fn2 = () => { return 1}
}
|
Q: 闭包是什么?
A: 闭包是指引用了另一个函数作用域中变量的函数,通过是在嵌套函数中实现。 —— 《红宝书 第四版》
Q: 类在 es5 es6 区别
A: es5 的类不继承 static 方法和成员
Q: 私有方法和私有成员
es6 不提供参考;ts 用 private,类似 c++;es5 使用表达式,如下:
1
2
3
4
|
function Class() {
let privateMember;
let privateFunc = () => {};
}
|
Q: 继承的方式
A: es6 用 extend, es5 有下面几种方式,详细翻红宝书:
- 原型链
- 盗用构造函数
- 组合继承
- 原型式继承
- 寄生式继承
- 寄生式组合继承
这是详细说下寄生式组合继承,因为这算是引用继承的最优方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
function inheritPrototype(subType, superType) {
let prototype = Object.create(superType.prototype); // 拷贝原型
prototype.constructor = subType; // 改变原型指向
subType.prototype = prototype; // 赋值给子类
}
// 基类
function SuperType(name) {
// 成员属性
this.name = name;
this.colors = ["red", "yellow", "green"];
}
// 成员方法
SuperType.prototype.sayName = function () {
console.log(this.name);
};
// 子类
function SubType(name, age) {
// super, 盗用构造函数
SuperType.call(this, name);
this.age = age;
}
// 寄生组合继承
inheritPrototype(SubType, SuperType);
// 子类成员方法
SubType.prototype.SayAge = function () {
console.log(this.age);
};
|
Q: new 的时候发生了啥
A: new 关键字会进行如下的操作:(摘自 MDN)
- 创建一个空的简单 JavaScript 对象(即{});
- 链接该对象(设置该对象的 constructor)到另一个对象 ;
- 将步骤 1 新创建的对象作为 this 的上下文 ;
- 如果该函数没有返回对象,则返回 this。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// 写成代码
function Fn(age) {
this.age = age;
}
const fn = new Fn(1)
(
// 用IIFE模拟
function () {
// 1. 创建空对象
let temp = {};
// 2. 把该对象的__proto__属性指向构造函数的原型链(prototype)
temp.__proto__ = Fn.prototype;
// 3. 用该对象做为this调用构造函数
Fn.call(temp, 1);
// 4. 返回“this”
return temp;
}
)();
|
Q: 箭头函数定义
A: 箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。 – 《MDN》
- 箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。
- 由于 箭头函数没有自己的this指针,通过 call() 或 apply() 方法调用一个函数时,只能传递参数(不能绑定this—译者注),他们的第一个参数会被忽略。(这种现象对于bind方法同样成立—译者注)
- 箭头函数不能用作构造器,和 new一起用会抛出错误。
- 箭头函数没有prototype属性。
- yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作函数生成器。