JavaScript
1. 数据类型
按存储类型分类:(基本类型)
number,string,boolean,undefined,null;(引用类型, 对象)Object,Array,Function;typeof:
number,string,boolean,undefined,null(object),function,array(object)instanceof:
A.__proto__ === B.prototype; 注意都是true:Object instanceof Function; Function instanceof Object; Function instanceof FunctionObject.prototype.toString.call相对有效比较稳的方法:
let class2type = {} 'Array Date RegExp Object Error'.split(' ').forEach(e => class2type[ '[object ' + e + ']' ] = e.toLowerCase()) function type(obj) { if (obj == null) return String(obj) return typeof obj === 'object' ? class2type[ Object.prototype.toString.call(obj) ] || 'object' : typeof obj }
2. new运算符的执行过程
例如:var a = new A();
创建一个新对象:
var obj = new Object(); obj.__proto__ = A.prototype;将构造函数的作用域赋给新对象(因此this就指向了这个对象):
A.bind(obj)执行构造函数中的代码(为这个新对象添加属性):
A()返回新对象(如果构造函数有自己 retrun 时,则返回该值)
polyfill:
function New (f) { var n = { '__proto__': f.prototype }; //步骤1 return function () { f.apply(n, arguments); //步骤2和3 return n; //步骤4 }; }
3. this 关键字
常见用法
- 对象的方法调用,this指向对象
- 函数调用中的 this,严格模式是 window,非严格模式是 undefined
- 构造函数中的this,指向构造函数的实例化对象
三种显式改变this绑定
call:
fn.call(target, 1, 2)apply:
fn.apply(target, [1, 2])配合 arguments 很好用,内部会转换成 call,所以效率上call更快bind:
fn.bind(target)(1,2)一般不立即执行的时候使用,bind 里面的 this 指向,不会被重写a.bind(b).call(c)最终的 this 是 b应用:
- 获取数组中的最大值和最小值:
Math.max.apply(Math, numbers); - 判断类型:
Object.prototype.toString.call(target) - 数组里面的使用需要注意:
arr[0]()等效arr.0.call(arr)
- 获取数组中的最大值和最小值:
this的绑定原则
- 严格模式下默认绑定的是
undefined, 非严格模式 this 指向了 window 和 global - setTimeOut 这样在函数中以函数作为参数的,非严格模式下this指向全局对象
- 优先级:new绑定 > 显式绑定 > 隐式绑定 > 默认绑定
fn(...args)等效fn.call(window [ES5-strict: undefined], ...args)
箭头函数
箭头函数表达式的语法比函数表达式更短,并且不绑定自己的this,arguments,super或 new.target。这些函数表达式最适合用于非方法函数(non-method functions),并且它们不能用作构造函数。
没有
arguments,使用rest参数的形式访问没有构造函数,所以不能使用
new没有原型
箭头函数中this直接指向的是调用函数的上一层运行时
一个特殊的对比
function test () { setTimeout(function () { console.log(this); }, 0) } test.call({a: 'this is obj'}) // Window function test () { (() => { console.log(this); })() } test.call({a: 'this is thisArg'}) // Object {a: 'this is thisArg'}
例子
var length = 10;
function fn() {
console.log(this.length);
}
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
}
};
obj.method(fn, 1);//输出是什么?
4. 数组方法(es6方法斜体)
通过Object.getOwnPropertyNames(Array.prototype)得到浏览器支持方法
9个会改变自身值的方法,使用需谨慎:
pop,push,reverse,shift,sort,splice,unshift,copyWithin,fillsort:各大浏览器的算法不是统一的splice:三个参数(起始下标、删除个数、添加元素),返回删除的项目数组集合
8个不会改变自身的方法:
concat,join,slice,toString,toLocateString,indexOf,lastIndexOf,includes,flat,flatMapconcat, slice:一般的数组拷贝可以使用它们,但是他们的集合里面如果有引用类型的对象,是不会复制的,只会继续引用includes:相比indexOf多一个查找NaN的能力[NaN, 1].includes(NaN); [NaN, 1].indexOf(NaN)>-1; // true; false
flat:多维数组拍平一维数组12个遍历的方法:
forEach,every,some,filter,map,reduce,reduceRight,find,findIndex,entries,keys,valuesforEach:将为数组中每一项执行一次函数,那些已删除,新增或者从未赋值的项将被跳过(但不包括值为 undefined 的项)
some:接收的方法返回true,后面的立即停止reduce:接收的参数第一个为累加器方法,这个方法有四个参数(accumulator,currentValue, currentIndex, array自身);第二个为初始值 initialValue,如果有初始值,作为第一个accumulator值,否则accumulator 的值为数组第一个,currentIndex 从1开始;在没有初始值的空数组上调用 reduce 将报错
map相比forEach多了个返回值,如果遍历对象不是引用类型就不会影响元素组的值entries,keys,values:涉及到迭代器
伪数组转换
- var arr = Array.prototype.slice.call(aLi)
- Array.from(arguments)
5. 深拷贝和浅拷贝
比较前还需要弄清除赋值,赋值
- 基本数据类型:赋值,赋值之后两个变量互不影响
- 引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象,相互之间有影响
简单来说可以理解为浅拷贝只解决了第一层的问题,拷贝第一层的基本类型值,以及第一层的引用类型地址。
浅拷贝的方法:
obj2 = Object.assign({}, obj);obj2 = {...obj};arr2 = arr.slice(0);arr2 = arr.concat([])
深拷贝的方法:
JSON.parse(JSON.stringify(obj))- 缺陷:
undefined、symbol和函数这三种情况,会直接忽略。- 循环引用情况下,会报错。
- 正则直接转对象了
- 缺陷:
lodash.cloneDeep()
6. 字符串方法
所有字符串方法都不会改变自身
操作:
slice,substr,substring,trim,toLowerCase,toUpperCase,toLocaleLowerCase,toLocaleUppercase,replace,split,toString,valueOf;查找比较:
charAt,charCodeAt,indexOf,lastIndexOf,search,match,localeCompare,includeshtml相关:
anchor,link,big,blink,bold等支持正则高阶用法:
match,search,replace,split
7. 正则
元字符
- 基本 --->
.\| - 字符组 --->
[][^][-] - 数量 --->
{m,n}{m,}{m}+*?| - 位置 --->
^$\b\B(?=p)(?!p) - 特殊 --->
\d\D\s\S\w\W - 标志 --->
gim
- 基本 --->
简写
\d(\D) digit --->[0-9]\w(\W) word --->[0-9a-zA-Z_]\s\Sspace --->[\t\v\n\r\f].--->[^\n\r\u2028\u2029]?--->{0,1}+--->{1, }*--->{0,}
惰性:数量相关的概念
- 默认贪婪
'aaaa'.match(/\w{2,5}/) // 'aaaa' - 加上
?转为惰性'aaaa'.match(/\w{2,5}?/) // 'aa'
- 默认贪婪
8. 模块化
CommonJS:
require/module.exports浏览器没有那两个关键字不支持,只能在 node 中使用从它分裂出 AMD
Asynchronous Module Definition规范(requireJS),可以作用在浏览器上基于它,CMD规范(seaJS),和 AMD 主要差别:AMD是一个依赖提前加载的概念,而CMD是同步执行,遇到require之后再执行当前的一个模块。两个都是单例模式。
ECMAScript6:
import/export相关:JS MODULE 大战