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
附上一张原型链的图
词法作用域与作用域链
作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。
ES5 只有全局作用域没和函数作用域,ES6 增加块级作用域
暂时性死区:在代码块内,使用 let 和 const 命令声明变量之前,该变量都是不可用的,语法上被称为暂时性死区。
Javascript 采用词法作用域(lexical scoping),也就是静态作用域。
函数的作用域在函数定义的时候就决定了。
当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。
什么是闭包
高级程序设计三:闭包是指有权访问另外一个函数作用域中的变量的函数。可以理解为(能够读取其他函数内部变量的函数)
闭包作用
- 独立作用域,避免变量污染
- 实现缓存计算结果
- 库的封装,例如 jQuery