跳到主内容

Javascript基础面试题

Javascript 基础是前端必备技能,也是面试官必考技能,不是说只要懂 Vue 或者 React,AngularJavascript 就可以了,懂原生 Javascript 才是最重要,毕竟框架也是原生 Javascript 写出来的

变量类型判断

数据类型检测

typeof 对于基本数据类型来说,除了 null 都可以显示正确的类型,typeof 对于对象来说,除了函数都会显示 object,此方案不是很好

typeof 5; // 'number'
typeof "5"; // 'string'
typeof undefined; // 'undefined'
typeof false; // 'boolean'
typeof Symbol(); // 'symbol'
console.log(typeof null); //object
console.log(typeof NaN); //number

typeof []; // 'object'
typeof {}; // 'object'
typeof console.log; // 'function'

为什么 typeof null 是 object

在 Javascript 中,对象都是使用二进制存储的,如果二进制前三位都是 0 的话,则表示 object 类型,而 null 的二进制全是 0,所以是 object。

instanceof 通过原型链来判断数据类型的,但是可以篡改原型链,不完善

p1 = new Person();
p1 instanceof Person; // true

Object.prototype.toString.call() 可以检测所有的数据类型,算是一个完美的方法

var obj = {};
var arr = [];
console.log(Object.prototype.toString.call(obj)); //[object Object]
console.log(Object.prototype.toString.call(arr)); //[object Array]

判断是否数组

console.log(Object.prototype.toString.call(arr)); //[object Array]
Array.isArray();

Javascript 原型和原型链

原型

每个对象都有一个隐式原型 __proto__ 属性,如果对象是通过 new 构造函数创建的,那么它的 __proto__ 指向的是构造函数的 prototype,例如

const obj = {}; // 隐式创建的对象
console.log(obj.__proto__ === Object.prototype); // true

function People(name) {
this.name = name;
}
const p = new People("1024nav");
console.log(p.__proto__ === People.prototype); // true

还有一个特殊的 Function 对象,Function 的 __proto__ 指向的是自身的 prototype

console.log(Function.__proto__ === Function.prototype); // true

对象 Object.prototype.__proto__ 是 null

console.log(Object.prototype.__proto__ === null); // true
console.log(Object.__proto__ === Function.prototype); // true

原型链

从上面的原型可以看出,一个对象的隐式原型 __proto__ 指向构造函数的 prototype,然而构造函数 prototype__proto__ 也是指向构造函数的构造函数prototype,这样就形成了一条链,一直到顶部为 null

还是上面的例子

function People(name) {
this.name = name;
}
const p = new People("1024nav");

console.log(p.__proto__ === People.prototype); // true
console.log(p.__proto__.__proto__ === Object.prototype); // true
console.log(p.__proto__.__proto__.__proto__ === null); // true
console.log(Function.__proto__ === Function.prototype); // true
console.log(People.__proto__ === Function.prototype); // true

附上一张原型链的图

prototype

词法作用域与作用域链

作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。

ES5 只有全局作用域没和函数作用域,ES6 增加块级作用域

暂时性死区:在代码块内,使用 let 和 const 命令声明变量之前,该变量都是不可用的,语法上被称为暂时性死区。

Javascript 采用词法作用域(lexical scoping),也就是静态作用域。

函数的作用域在函数定义的时候就决定了。

当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。

什么是闭包

高级程序设计三:闭包是指有权访问另外一个函数作用域中的变量的函数。可以理解为(能够读取其他函数内部变量的函数)

闭包作用

  1. 独立作用域,避免变量污染
  2. 实现缓存计算结果
  3. 库的封装,例如 jQuery