0%

基本数据类型

指简单的数据段。基本数据类型存储在栈内存中。

不能给基础数据类型添加属性。

  • 存储原始数据类型
  • 按值访问
  • 存储的值大小固定
  • 由系统自动分配内存空间
  • 空间小,运行效率高
  • 先进后出,后进先出

String

阅读全文 »

发布订阅者模式

发布订阅模式

  1. 消息中心:负责存储消息与订阅者的对应关系,有消息触发时,负责通知订阅者
  2. 订阅者:去消息中心订阅自己感兴趣的消息
  3. 发布者:满足条件时,通过消息中心发布消息

实现

var broastEvent = {
    // 消息监听队列
    clientList: {},
    // 订阅(监听)消息
    listen: function(observer, action) {
        if (clientList[observer]) { // 如果已经存在订阅消息了
            this.clientList[observer].push(action) // 新增监听
        } else {
            this.clientList[observer] = [].concat(action)
        }
    },
    // 发布(触发)消息
    trigger: function(observer, ...args) {
        const actionList = this.clientList[observer] || []
        if (actionList.length > 0) {
            actionList.forEach(fn => {
                fn(...args)
            })
        }
    },
    // 移除消息监听
    remove: function(observer) {
        this.clientList && delete this.clientList[observer]
    }
}


// 测试
broastEvent.listen('some', function (...args) {
    console.log('some: ', args, this)
}.bind(this))

broastEvent.listen('some2', (...args) => {
    console.log('some2: ', args, this)
})
setTimeout(() => {
    broastEvent.trigger('some', 123, 234)
    broastEvent.trigger('some2', 123, 234)
    broastEvent.remove('some2')
}, 2000)
setTimeout(() => {
    broastEvent.trigger('some2', 123, 234)
    broastEvent.trigger('some', 123, 234)
}, 5000)
// some:  [ 123, 234 ] {}
// some2:  [ 123, 234 ] {}
// some:  [ 123, 234 ] {}
阅读全文 »

参考《你不知道的JavaScript(中卷)》第2章28页

引用就像一种特殊的指针,是来指向变量的指针(别名)。如果参数不声明为引用的话,参数值总是通过值复制的方式传递,即便对复杂的对象值也是如此。

JavaScript 中没有指针,引用的工作机制也不尽相同。在 JavaScript 中变量不可能成为指向另一个变量的引用。

JavaScript 引用指向的是值。如果一个值有 10 个引用,这些引用指向的都是同一个值, 它们相互之间没有引用 / 指向关系。

JavaScript 对值和引用的赋值 / 传递在语法上没有区别,完全根据值的类型来决定。

阅读全文 »

进程Process

进程是资源分配和调度的最小单位。

进程有独立的地址空间。

一个程序至少有一个进程,一个进程至少有一个线程。

线程Thread

阅读全文 »

方法1 setTimeout

function timeoutify(fn, delay) {
    var intv = setTimeout(function() {
        intv = null;
        fn(new Error("Timeout!"));
    }, delay);

    return function() {
        // 还没有超时
        if (intv) {
            clearTimeout(intv);
            fn.apply(this, arguments);
        }
    }
}

方法2 promise

// 使用promise.race 竞速 promise状态一旦决议就无法改变
function test() {
    return new Promise((resolve, reject) => {
        setTimeout(function() {
            console.log('test')
            resolve('test')
        }, 3000)
    })
}

function timeoutfn() {
    return new Promise((resolve, reject) => {
        setTimeout(function() {
            console.log('timeoutfn')
            resolve('timeoutfn')
        }, 4000)
    })
}

Promise.race([
    test(), 
    timeoutfn()
]).then(res => {
    console.log('race end')
}).catch(err => {
    console.log('race err')
})

防抖的原理:触发事件,但在事件触发 n 秒后才执行,如果在一个事件触发的 n 秒内又触发了这个事件,那就以新的事件时间为准,n 秒后才执行。总之,就是要等触发完事件 n 秒内不再触发事件,才执行。

应用场景input输入

实现

function debounce(func, wait, immediate) {
    var timeout = null, result;
    return function() {
        var context = this; // 修改this指向,避免指向window
        var args = argumenets; // 传参
        
		if (timeout) clearTimeout(timeout); // 等触发完事件n秒后执行
        if (immediate) { // 立即执行第一次 immediate判断是否立即执行
            // 如果已经执行过,不再执行
            var callNow = !timeout; // !null = true   !12 = false
            timeout = setTimeout(function() {
                func.apply(context, args)
            }, wait)
            if (callNow) { // 第一次执行
                result = func.apply(context, args)
            }
        } else {
            timeout = setTimeout(function() {
                func.apply(context, args)
            }, wait)    
        }
        return result; // 只有立即执行模式才能返回结果
    }
}

添加取消模式

阅读全文 »

节流的原理是:固定时间间隔执行函数

应用场景:resizescroll

function throttle(func, wait) {
    var timeout, context, args;
    var previous = 0;

    var later = function() {
        previous = +new Date();
        timeout = null;
        func.apply(context, args)
    };

    var throttled = function() {
        var now = +new Date();
        //下次触发 func 剩余的时间
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        // 如果没有剩余的时间了或者你改了系统时间
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            func.apply(context, args);
        } else if (!timeout) {
            timeout = setTimeout(later, remaining);
        }
    };
    return throttled;
}

function throttle2(func, wait) {
    var timeout = null;
    var previous = 0;

    return function() {
        var args = arguments;
        var context = this;
        var now = +new Date(); 
        var remainning = wait - (now - previous); // 等待时间减去两次触发事件的时间差
        timeout && clearTimeout(timeout)
        if (remainning <= 0) { // 两次触发时间差大于等待时间,立马执行
            func.apply(context, args)
            previous = now // 更新时间
        } else { // 小于等待时间,等待一段时间后执行
            timeout = setTimeout(function () {
                func.apply(context, args)
                provious = +new Date()
            }, remainning) // 修改设置timeout时间
        }
    }
}

我们可以看到:鼠标移入,事件立刻执行,晃了 3s,事件再一次执行,当数字变成 3 的时候,也就是 6s 后,我们立刻移出鼠标,停止触发事件,9s 的时候,依然会再执行一次事件。

优化
阅读全文 »