开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 15 天,点击查看活动详情
前言
我觉得我也不见得比别人差太多
BEGIIN
js——常识总结
判断方式:数组,对象
判断数组方式?
arr.**proto**=== Array.prototype
Array.isArray(arr)
arr instanceOf Array
Array.prototype.isPrototypeOf(arr)
Array.prototype.toString.call(arr).slice(8, -1) ==== 'Array'
判断对象方式?
Array.prototype.toString.call(obj)
obj.constructor === Object
obj instanceOf Object
typeof (null 也是Object)
遍历对象方式
for in 依次访问一个对象以及原型链上所有可访问的属性
Object.keys 返回一个数组 包含所有可枚举的属性名称
Object.getOwnPropertyNames 返回一个数组包含不可枚举的属性
深浅拷贝、赋值
赋值
定义:赋值都是该对象的栈中地址,而不是堆中的数据 所有类型全部都相互影响
浅拷贝
Object.assign()
function shallowClone(obj) {\
return Object.assign({}, obj);
}
展开运算符(...)
function shallowClone(obj) {
return {...obj};
}
使用数组的 slice() 函数或对象的 Object.keys() 函数`
let arr = [a,3]
let arr2 = arr.slice()
函数库loadsh中的_.clone 方法
深拷贝
常见的方法包括使用 JSON.parse 和 JSON.stringify、
const original = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(original));
使用递归算法:deepClone()
const mapTag = '[object Map]';
const setTag = '[object Set]';
const arrayTag = '[object Array]';
const objectTag = '[object Object]';
const boolTag = '[object Boolean]';
const dateTag = '[object Date]';
const errorTag = '[object Error]';
const numberTag = '[object Number]';
const regexpTag = '[object RegExp]';
const stringTag = '[object String]';
const symbolTag = '[object Symbol]';
function isObject(target) {
const type = typeof target;
return target !== null && (type === 'object' || type === 'function');
}
function getType(target) {
return Object.prototype.toString.call(target);
}
function getInit(target) {
const Ctor = target.constructor;
return new Ctor();
}
function clone(target, map = new WeakMap()) {
// 克隆原始类型
if (!isObject(target)) {
return target;
}
// 初始化
const type = getType(target);
let cloneTarget;
if (deepTag.includes(type)) {
cloneTarget = getInit(target, type);
}
// 防止循环引用
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
// 克隆set
if (type === setTag) {
target.forEach(value => {
cloneTarget.add(clone(value,map));
});
return cloneTarget;
}
// 克隆map
if (type === mapTag) {
target.forEach((value, key) => {
cloneTarget.set(key, clone(value,map));
});
return cloneTarget;
}
// 克隆对象和数组
const keys = type === arrayTag ? undefined : Object.keys(target);
forEach(keys || target, (value, key) => {
if (keys) {
key = value;
}
cloneTarget[key] = clone(target[key], map);
});
return cloneTarget;
}
使用 lodash_.cloneDeep 方法
bind实现原理
-
可以指定this
-
返回一个函数
-
可以传入参数
-
可以用new 操作符
注:不是函数调用会报错
Function.prototype.bind1 = function(context){
if(typeof this !== 'function'){
throw new Error(this must be function);
}
var self = this;
var args = Array.prototype.slice.call(arguments,1);
let fNop = function(){};// 作为中介,重写原型对象,代之为构造函数的实例
let fBound = function(){
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fBound ? this:context ,args.concat(bindArgs));
}
fNop.prototpye = this.prototype;
fBound.prototype = new fNop(); //
return fBound;
}
bind VS call VS apply
new实现原理
- 创建了一个对象
- 设置原型 将对象的原型设置为函数的prototype对象
- 吧this 指向对象,执行构造函数的代码
- 判断函数的返回值类型
- 如果是值 返回创建的对象 若是引用对象 就返回这个引用类型的对象
function news(constructor, ...param) {
const obj = {}
obj.__proto__ = constructor.prototype
const res = constructor.apply(obj, param)
return res instanceof **Object** ? res : obj
}
instanceof实现原理
instanceof主要用于判断某个实例是否属于某个类型,也可用于判断某个实例是否是其父类型或者祖先类型的实例。
instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false。
function instanceofs (left, right) {
let B = right.prototype
while(true) {
if (left === null) {
return false
}
if (left === B) {
return true
}
left = left.__proto__
}
}
typeof VS instanceof
①返回值不同: typeof 返回数据类型;instanceof返回布尔值
②null,对象,数组都会返回‘object’,局限性;instanceof用于判断对象,形式为:obj1 instanceof obj2(obj1 是否是 obj2的实例),obj2必须是对象,否则会报错。
js——闭包
定义:有权访问另一个函数作用域的变量的一个函数 / 函数块以及函数定义时所在的词法环境两者的结合就是闭包
作用:
- 希望变量长期驻扎在内存中
- 避免全局变量的污染
JS执行上下文
要经过浏览器V8编译后才能执行。比如 变量提升,函数提升
js代码运行需要一个环境,就是js执行上下文。js运行前的预编译也是这个环境进行的
全局执行上下文:代码开始执行时首先进入的环境
函数执行上下文:函数调用时,会开始执行函数中的代码
eval执行上下文 :不建议使用
周期:
-
创建阶段
- 创建词法环境
- 生成变量对象(vo),建立作用域链
- 确认this指向, 并绑定this
-
执行阶段
- 这个阶段进行变量复制,函数引用及执行代码
预编译发生在函数执行之前
-
四步:
- 创建AO对象
- 找形参和变量声明,将变量和形参作为AO属性名,值为undefined
- 将实参和形参相统一
- 在函数体里找到函数声明,值赋予函数体,最后程序输出变量值的时候,就是从AO拿
js——设计模式
最重要思想:
- 开放封闭原则
- 对扩展开放
- 对修改封闭
工厂模式
定义: 用一个工厂函数,来创建实例,隐藏new
如:jQuery $函数;React createElement 函数
单例模式
定义:全局唯一的实例
如:Vuex Redux 的store; 全局唯一的dialog modal
JS是单线程,创建单例很简单
代理模式
定义:使用者不能直接访问对象,必须要通过代理。如:proxy