js之各种实现

[1,2,3].map(parseInt) // 1, NaN, NaN
复制代码
// 实现连续的密集数组
Array.from({length: 100})
Array.apply(null, {length: 100})
[...Array(100)]
(function(){
    let i = 0
    let a = []
    let timer = setInterval(() => {
        if(i < 100){
            a.push(i)
            i++
        }else{
            clearInterval(timer)
            console.log(a)
        }
    })
})()
(function(){
    let i = 0
    let a = []
    function addItem(){
        if(i < 100){
            a.push(i)
            i++
            requestAnimationFrame(addItem)
        }else{
            console.log(a)
        }
    }
    
    requestAnimationFrame(addItem)
})()
复制代码
function Foo () {
    getName = function () { alert(1) }
    return this
}
Foo.getName = function () { alert(2) }

Foo.prototype.getName = function () { alert(3) }

var getName = function () { alert(4) }

function getName () { alert(5) }

//输入的值
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

// 答案 2 4 1 1 2 3 3

复制代码

数组扁平化

function flatDeep(arr){
    return Array.isArray(arr) ? arr.reduce((a, b) => [...a, ...flatDeep(b)], [])
}
function flatDeep(arr, origin){
    origin = origin || []
    return Array.isArray(arr) ? arr.map(item =>{flatDeep(item, origin)}) : origin.push(arr)
}
let a = []
flatDeep([1, [[2], [3, [4]], 5]], a)
复制代码
0.1 + 0.2 != 0.3
// 计算机内部十进制整数转二进制方法:除2取余;十进制小数转二进制方法:乘2除整
0.1 * 2 = 0.2 取整 0
0.2 * 2 = 0.4 取整 0
0.4 * 2 = 0.8 取整 0
0.8 * 2 = 1.6 取整 1
0.6 * 2 = 1.2 取整 1
0.2 * 2 = 0.4 取整 1
。。。
因此0.1 在计算机里理论上应该是无限循环的二进制数,
但是计算机不可能无限大,因此后面的位数会被舍掉
js是遵循IEEE754标准的语言,二进数由64位表示,
一位表示符号位,11位为指数位,后52位表示有效数字,存储小数
复制代码

call和apply方法实现

Function.prototype.call2 = function(context){
    context = context || window
    context.fn = this
    let args = [...arguments].slice(1)
    let result = context.fn(...args)
    delete context.fn
    return result
}
Function.prototype.apply2 = function(context){
    context = context || window
    context.fn = this
    var result
    if(arguments[1]){
        result = context.fn(...arguments[1])
    }else{
        result = context.fn()
    }
    delete context.fn
    return result
}
复制代码

bind方法实现

Function.prototype.bind2 = function(context){
    let self = this
    context = context || window
    let args = [].slice.call(arguments, 1)
    var fBound = function(){
        let bindArgs = [].slice.call(arguments)
        return self.apply(this instanceof fBound ? this : context, args.concat(bindArgs))
    }
    fBound.prototype = Object.create(self.prototype)
    return fBound
}
复制代码

new方法实现

function _new(){
    let context = {}
    let args = [].slice.call(arguments)
    let con = args.shift()
    context = Object.create(con.prototype)
    let ret = con.apply(context, args)
    return (typeof ret == 'object' && ret != null) ? ret : context
    
}
复制代码

js创建对象的方式

// 工厂模式
function createObj(name){
    let obj = {}
    obj.name = name
    obj.say = function(){
        return obj.name
    }
}
// 构造函数模式
function Person(name){
    this.name = name
    this.say = function(){
        return this.name
    }
}
var person = new Person('Mike')
// 原型模式
function Person(){}
Person.prototype.name = 'Mike'
Person.prototype.say = function(){
    return this.name
}
// 构造函数和原型组合模式
function Person(name){
    this.name = name
}
Person.prototype.say = function(){
    return this.name
}
var person = new Person('Mike')
// 动态原型模式
function Person(name){
    this.name = name
    if(typeof this.say !== 'function'){
        Person.prototype.say = function(){
            return this.name
        }
    }
}
// 寄生构造函数模式
function Person(name){
    let obj = {}
    obj.name = name
    obj.say = function(){
        return this.name
    }
    return obj
}
// 稳妥构造函数模式
function Person(name){
    let obj = {}
    obj.say = function(){
        return name
    }
    return obj
}
复制代码

js继承

// 原型继承
function Parent(){
    this.name = 'Mike'
}
function Child(){}
Child.prototype = new Parent()
Child.prototype.constructor = Child
console.log(new Child().name) // Mike
// 构造函数继承
function Parent(name){
    this.name = name
}
function Child(name){
    Parent.call(this, name)
}
// 原型和构造函数组合模式
function Parent(name){
    this.name = name
}
Parent.prototype.say = function(){
    return this.name
}
function Child(name){
    Parent.call(this, name)
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
console.log(new Child('Mike').say())
// 原型式继承
function createObj(proto){
    function F(){}
    F.prototype = proto
    return new F()
    // 等价于
    return Object.create(proto)
}
// 寄生组合继承
function Parent(name){
    this.name = name
}
Parent.prototype.say = function(){
    return this.name
}
function Child(name){
    Parent.call(this, name)
    this.age = 8
    
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
let child = new Child('Mike')
console.log(child instanceof Child) // true
console.log(child instanceof Parent) // true
复制代码

js原型与原型链

原型与原型链

js类型判断

基本类型判断 typeof 但是typeof null === 'object' typeof (function a(){}) === 'function'

实例判断 instanceof new Person() instanceof Person

内置对象 toString 可以判断的类型有
var number = 1;          // [object Number]
var string = '123';      // [object String]
var boolean = true;      // [object Boolean]
var und = undefined;     // [object Undefined]
var nul = null;          // [object Null]
var obj = {a: 1}         // [object Object]
var array = [1, 2, 3];   // [object Array]
var date = new Date();   // [object Date]
var error = new Error(); // [object Error]
var reg = /a/g;          // [object RegExp]
var func = function a(){}; // [object Function]
Object.prototype.toString.call(Math); // [object Math]
Object.prototype.toString.call(JSON); // [object JSON]
Object.prototype.toString.call(arguments); // [object Arguments]
// 判断是否为plainObject--由Object创建的对象,或者原型为null的对象
function plainObject(obj){
    let class2type = {}
    hasOwn = class2type.hasOwnProperty
    if(typeof obj != 'object' || !obj) return false
    let proto = Object.getPropertyOf(obj)
    if(!proto){
        return true
    }
    let ctor = proto.constructor
    // 对于函数的toString方法判断,要找Function.property上的toString方法
    return typeof ctor === 'function' && hasOwn.toString.call(ctor) === hasOwn.toString.call(Object)
}
复制代码

js深浅拷贝

function shallow(src){
    if(typeof src === 'object'){
        let target = src instanceof Array ? [] : {}
        for(let key in src){
            if(src.hasOwnProperty(key){
               target[key] = src[key] 
            }
        }
        return target
    }
    return
}
function deep(src){
    if(typeof src === 'object'){
        let target = src instanceof Array ? [] : {}
        for(let key in src){
            if(src.hasOwnProperty(key)){
                target[key] = typeof src[key] == 'object' ? deep(src[key]) : src[key]
            }
        }
        return target
    }
    return
}
function deepObject(src){
    let copy = Object.create(Object.getPropertyOf(src)
    copyProperties(src, copy)
    return copy
    function copyProperties(src, copy){
        Object.getOwnPropertyNames(src).forEach(propKey => {
            Object.defineProperty(copy, propKey, Object.getPropertyDescriptor(src, propKey))
        })
    }
}
function deepObjectEs7(src){
    return Object.create(Object.getPropertyOf(src), Object.getOwnPropertyDescriptors(src))
}
复制代码

防抖

// 多用于鼠标事件,滚动事件,表示当事件停止一定时间后响应
function debounce(func, wait){
    var timer
    return function(){
        let args = arguments
        let context = this
        clearTimeout(timer)
        timer = setTimeout(() => {
            func.apply(context, args)
        }, wait)
    }
}
function debounce(func, wait, immediate){
    var timer
    return function(){
        let args = arguments
        let context = this
        if(timer) clearTimeout(timer)
        if(immediate){
            let callNow = !timer
            timer = setTimeout(() => {
                timer = null
            })
            if(callNow){
                func.apply(context, this)
            }
        }else{
            timer = setTimeout(() => {
                func.apply(context, this)
            }, wait)
        }
    }
}
复制代码

节流

// 多用于文本输入,表示在用户连续输入期间,一定时间间隔后响应,定期发生
// 时间戳实现方式 满足立即执行一次
function throttle(func, wait){
    let prev = 0
    return function(){
        let context = this
        let args = arguments
        let now = + new Date()
        if(now - prev > wait){
            func.apply(context, args)
            prev = now
        }
    }
}
// 定时器实现方式 满足离开后还会执行一次
function throttle(func, wait){
    let timer
    return function(){
        let context = this
        let args = arguments
        if(!timer) {
            timer = setTimeout(() => {
                func.apply(context, args)
                timer = null
            },wait)
        }
    }
}
// 第三版 
function throttle(func, wait){
    let timer
    let prev = 0
    let context 
    function later(){
        timer = null
        func.apply(context, args)
        prev = + new Date()
    }
    return function(){
        context = this
        let args = arguments
        let now = + new Date()
        let remain = wait - (now - prev)
        if(remain < 0 || remain > wait){
            if(timer){
                clearTimeout(timer)
                timer = null
            }
            func.apply(context, args)
        }else if(!timer){
            timer = setTimeout(later, remain)
        }
        
    }
}
// leading: 是否立即执行
// tailing: 最后一次是否执行
function throttle4(func, wait, options) {
    let prev = 0
    let timer
    let result
    if (!options) {
        options = {}
    }
    return function () {
        let context = this
        let args = arguments
        let now = + new Date()
        if (!prev && !options.leading) {
            pre = now
        }
        let remaining = wait - (now - prev)
        if (remaining < 0 || remaining > wait) {
            if (timer) {
                clearTimeout(timer)
                timer = null
                prev = now
            }
            result = func.apply(context, args)
        } else if (!timer && options.tailing) {
            this.timer = setTimeout(() => {
                func.apply(context, args)
                timer = null
                prev = options.leading == false ? 0 : new Date()
            }, remaining)
        }
        return result
    }
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值