一、安全类型检测
1、比较基础的方案(instanceof)
let data = [1]
console.log(data instanceof Array) // true
对于typeof
2、强行转义
let data = [1]
Object.prototype.toString.call(data) === '[objectd Array]'
*注意:*使用call,非直接调用,call的第一个参数是context执行上下文,把数组传入作为执行上下文(this)
3、es6 类检测
class Person{}
toString.call(Person) // [object function]
toString.call(new Person()) // [object Object]
class是使用function实现,也就是说class == function
二、惰性载入函数
在代码中做一些兼容性判断,做一些ua的判断
包括做函数、类存在的判断,都可以借鉴
//UA的类型
getUAType: function() {
let ua = window.navigator.userAgent;
if (ua.match(/renren/i)) {
return 0;
}
else if (ua.match(/MicroMessenger/i)) {
return 1;
}
else if (ua.match(/weibo/i)) {
return 2;
}
return -1;
}
三、函数绑定
其实就是在类中尽量去改变执行上下文,减少this改变导致执行出错
- bind不会立即调用,而是返回一个新的函数,称为绑定函数,this指向的是第一个参数,第二个及以后的参数作为原函数的参数进行调用
- apply和call都是为了改变某个函数(内部this的指向)运行时而存在的,调用返回的是执行结果;第一个参数改变this
- apply第二个参数为数组
- call第二个参数及其后的参数都是变量,非数组
四、柯里化
柯里化就是函数与参数结合产生一个新的函数,重点就是需要返回一个函数,也就是链式调用
Function.prototype.curry = function() {
let slice = Array.prototype.slice;
let defaultArgs = slice.call(arguments);
let that = this;
return function() {
return that.apply(this,defaultArgs.concat(slice.call(arguments)));
}
};
五、防止篡改对象
1、Object.seal防止新增和删除属性:
let person = {}
Object.seal(person)
delete person.name
person.age = 12
非严格模式不会抛异常,但是执行无效;严格模式下会抛异常:
2、Object.freeze冻结对象
同时可以使用Object.isFrozen、Object.isSealed、Object.isExtensible判断当前对象的状态。
let person = {}
Object.freeze(person)
delete person.name
person.age = 12
执行会抛异常
3、defineProperty冻结单个属性
let person = {}
Object.defineProperty(person,'age', {
enumerable: false, // 不能枚举、遍历
writable: false, // 不能进行编辑,写入
value: 12
})
六、函数节流throttle
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
场景:
- 监听input触发搜索
- 监听resize做响应式调整
- 监听mousemove调整位置
节流两种形式:时间戳版和定时器版。
时间戳版:
function throttle(func, wait) {
let previous = 0;
return function() {
let now = Date.now();
let context = this;
let args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
定时器版:
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
七、函数防抖deboucing
所谓防抖,指的是在触发事件后,n秒内函数只响应一次,如果在n秒内重复触发,则会重新计算函数执行时间
场景:
- 滚动
- 暴击
防抖两种形式:前缘响应(立即执行)和后缘响应(非立即执行)。
- 前缘响应:事件第一次触发时响应;倒计时一段时间内不会响应,并且如果在此时间内再次触发,会重置倒计时
- 后缘响应:在事件第一次触发后开始倒计时,如果这段时间没有触发,则响应,否则,重置倒计时
非立即执行:
function debounce(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args)
}, wait);
}
}
立即执行:
function debounce(func,wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
}
合并立即和非立即双剑合璧:
/*
* immediate: true立即,false为非立即
*/
function debounce(func,wait, immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
if(immediate) {
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
timeout = setTimeout(() => {
timeout = null;
}, wait)
}
}
}
技术分享,希望大家能共同进步,共同学习,如果我有那部分分析错了,麻烦不要珍惜你的金口良言,使劲怼,日天日地才是好朋友