web前端面试问答

每次面试官问起基础的概念,明明心里头明镜似水,却总是支支吾吾说不清楚。无奈~
想想还是要把概念用自己的话说出来,这才是自己的!

原型、构造函数、实例

  • 原型:函数里有一个特殊的属性prototype也被称作原型
  • 构造函数:用于对象初始化的函数
  • 实例:用关键字new调用构造方法得到的对象就是这个构造函数的实例

原型链

每一个实例对象都有一个__proto__属性指向该构造函数的原型对象,并且该原型对象也有一个自己的原型对象__proto__,像这样层层往上,直到一个对象的原型对象为null。这个环节就被称为原型链。

执行上下文,变量声明,作用域,作用域链

执行上下文

程序在执行中,会进入到一个执行上下文阶段,可以叫执行环境阶段。

创建执行环境主要有下面三种情况:

* 全局环境:当代码执行时就会进入全局环境
* 函数环境:当代码进入函数时就会产生函数环境
* eval环境:当使用eval函数时就会产生eval环境

执行上下文主要包含了,变量对象,作用域链,this的指向

1
2
3
4
5
6
//用伪代码表示
ExecutionContexts = {
VariableObject:{}, //变量对象
scopeChain:[], // 作用域链
this:{} // this指向
}

  • 变量对象

变量对象的创建,需要经历下面三个流程

  1. 创建一个参数名称和对应值的对象,如果没有实参,则会创建一个值为undefined的属性对象(如果是在函数上下文中)
  2. 创建一个函数名和函数体组成(function-object)的变量对象,如果有重复,则完全覆盖这个属性。
  3. 创建一个变量名和变量值(undefined)组成的变量对象,如果有重复,为了防止覆盖后的值为undefined,跳过当前变量声明。

AO与VO的关系:未进入执行阶段之前,变量对象(VO)中的属性都不能访问!但是进入执行阶段之后,变量对象(VO)转变为了活动对象(AO),里面的属性都能被访问了,然后开始进行执行阶段的操作。

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 foo(a) {
var b = 2;
function c() {}
var d = function() {};

b = 3;

}

foo(1);


// 进入执行上下文的AO
AO = {
arguments: { // 调用函数时,会为其创建一个Arguments对象,并自动初始化局部变量arguments,指代该Arguments对象。所有作为参数传入的值都会成为Arguments对象的数组元素。
0: 1,
length: 1
},
a: 1,
b: undefined,
c: reference to function c(){},
d: undefined
}

作用域

作用域就是创建变量时的区域,规定了当前执行代码对变量的访问权限

JavaScript分为全局作用域,局部作用域,和块级作用域。

  • 全局作用域
  • 局部作用域
  • 块局级作用域
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
// 例1
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();


// 例2
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();


// 两段代码都会打印:local scope。

JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。 —-《JavaScript权威指南》

作用域链