最近读了Javascript Enlightenment。整体感觉还是比较基础的。这里记录跟扩展下其中一些知识点。
Math
JS里有个不成文的规定,构造函数首字母大写。所以可能容易让人产生误解Math是构造函数。其实Math只是一个简单的封装了很多数学相关方法的对象。
console.log(typeof Math); //"object"
console.log(typeof Array); //"function"复制代码
Function
构造一个函数实例有2种方法:
- 函数声明
function sum(x, y) {
return x + y;
}
console.log(sum(3,4)); //7复制代码
- 通过构造函数
let multiply = new Function("x", "y", "return x * y;");
console.log(multiply(3,4)); //12复制代码
工作中经常会有需要用到call或者apply来切换函数执行上下文的情况。例如:
function print(){
console.log(this.a);
}
print.call({a: 'hello'}); //hello复制代码
有些面试题可能会问为啥print上没有定义call方法,但是print.call()调用为啥不会报错。其实是因为print是Function的一个实例化对象,call方法定义在Function.prototype上,通过原型链查找到的call方法。
数组判断
typeof可以用来判断基础类型,无法用typeof区分数组跟对象。
console.log(typeof [1,2]); //object
console.log(typeof {}); //object复制代码
可以有下面2种常见的方法区分数组:
- 原生API: Array.isArray
console.log(Array.isArray([1,2])); //true复制代码
- toString
console.log(Object.prototype.toString.call([1,2])
.toLowerCase() === '[object array]'); //true复制代码
这里注意下,我们使用了toString方法,然后用call方法切换toString调用时的上下文为我们要进行判断的数组。所以有些人会误以为Object.prototype.toString.call([1,2])跟 [1,2].toString()是等价的。其实不然:
console.log(Object.prototype.toString.call([1,2])); //[object Array]
console.log([1,2].toString()); //1,2复制代码
这是因为原型链查找有个就近原则。所以当使用[1,2].toString的时候,查找到并被使用的是Array.prototype.toString,这个方法覆盖了Object.prototype.toString。
delete 操作符
delete只会删除自身属性。不会删除原型链上的属性。
let obj = {a: 'self'};
Object.prototype.a = 'prototype';
console.log(obj.a); //self
delete obj.a;
console.log(obj.a); //prototype
delete Object.prototype.a;
console.log(obj.a); //undefined复制代码
全局对象
访问全局对象有2种方法:
- 变量方法: 浏览器里用window, Node里用global
- 在全局作用域里使用 this
当我们访问一个变量的时候会形成一个作用域链。作用域的顶端就是全局变量(i.e. 全局对象下的对应变量)。相对应的我们也有全局函数和全局属性。曾经有一段代码坑了我下:
console.log(hasOwnProperty); //ƒ hasOwnProperty() { [native code] }复制代码
刚开始我以为输出应该是undefined因为印象中hasOwnProperty并非是全局函数。通过下面的例子大家可以想下为什么hasOwnProperty不是全局函数但是上面的输出不是undefined ~
Object.prototype.hasOwnProperty.call(window, 'encodeURI'); // true
'hasOwnProperty' in window //true
Object.prototype.hasOwnProperty.call(window, 'hasOwnProperty'); // false复制代码
undefined vs null
undefined代表没值。有2种情况可能出现没值。
- 定义了变量但是未赋值
let s;
console.log(s); //undefined复制代码
- 未定义
let obj1 = {};
console.log(obj1.a); //undefined复制代码
null表示有值,null是这个特殊的值。
let obj2 = {a: null};
console.log(obj2.a); //null复制代码
如果需要同时过滤undefined跟null的话,可以使用弱等于检查。
console.log(null == undefined); //true
let arr = [null, undefined, 1];
let fil = arr.filter(it => {
return it != null;
});
console.log(fil); //[1]复制代码
另外undefined其实也是个全局变量, 但是null确不是。null也不挂载在window下。那么null是哪来的呢?
window.hasOwnProperty('undefined'); //true
window.hasOwnProperty('null'); //false
window.null //undefined复制代码
Reference
Javascript Enlightenment
Notice
- 如果您觉得该Repo让您有所收获,请「Star 」支持楼主。
- 如果您想持续关注楼主的最新系列文章,请「Watch」订阅