【前端24_JS加强】封装(订阅者 + 发布者)、深复制 & 浅复制、内存、this指针


Javascript 进阶

封装(订阅者 + 发布者)

提出问题

问题描述:假如我是一个推销产品的应用开发经理,有很多的用户在我的平台上订阅些内容,我如何通过用户订阅的信息,准确的发送产品给需要它的客户们呢?

分析问题

  • 首先我是卖家,我需要提供一个添加订阅信息和对应的用户功能函数
  • 当我发布一个产品的时候,我需要精准的发送给需要它的用户
步骤
// 我们先创建一个卖家
var seller = {};

// 添加一个列表list,用于存储订阅者
seller.list = [];

// 添加一个方法listen,用于添加订阅者
seller.listen = (fn) => seller.list.push(fn);

// 添加一个方法trigger:用于发布消息
seller.trigger = function(){
	// 循环停止条件:如果循环复制的值为none/undefined的时候
	for (var i = 0, fn; fn = this.list[i]; i++) {
		// this 指向seller,让每一个订阅者都继承发布产品的参数
		fn.call(this,...arguments)
	}
}

// 添加订阅者A
seller.listen(function(color, size){
	console.log('我是A订阅者');
	console.log("您订阅的卖家发布新的鞋:");
	console.log("颜色是:", color);
	console.log("尺寸是:", size);
})

// 添加订阅者B
seller.listen(function(color, size){
	console.log('我是B订阅者');
	console.log("您订阅的卖家发布新的鞋:");
	console.log("颜色是:", color);
	console.log("尺寸是:", size);
	
})

// 卖家发布一双新鞋,通知给订阅者
seller.trigger('红色', 42)

这样一个简单的发布过程就做好了,然而这并不是定制,因为每次发布一个产品,都要通知所有的订阅者,我们的目的是通过订阅者订阅的关键字,来精准的发布产品给有需要的客户,这次我们用对象来写

// 这是一套流程,相当于数学公式
var method1 = {
    // 列表属性,保存用户及订阅信息
    // list: ['手机': ['订阅者A','订阅者B'], '电脑': ['订阅者','订阅者']]
    list: [],

    // 添加用户及其订阅信息
    // key代表关键字,user是关注关键字的用户
    listen(key, user){
        // 如果当前list中没有此订阅信息的人,就初始化一个空的
        if(!this.list[key]){
            this.list[key] = []
        }
        // 然后把这个用户给添加进来
        this.list[key].push(user)
    },

    // 发布商品:发布商品的时候需要通过关键字来精准的推广给相应用户
    trigger(){
        // 获取到用户订阅的关键字
        let key = Array.prototype.shift.call(arguments);

        // 通过订阅关键字来获得相应订阅用户列表
        let user = this.list[key];
        // 如果没有此关键字的订阅,或者订阅此关键字的人数为空,则不需要通知
        // console.log(user);
        if(!user || user.length === 0){
            return ;
        }

        // 发布给订阅用户列表中的用户
        for(let i = 0, each;each = user[i++];){
            // 给 each 订阅者们,传递发布的消息argument
            // 不需要修改指针
            // each.call(this,...arguments)     也可以这么写
            each(...arguments);
            // console.log(each);
        }
    }
};

// 入口:给转进来的对象加入method1方法
var init = function(obj){
    for(var key in method1){
        obj[key] = method1[key];
    }
};

// 通过数学公式,创建一个卖家,并初始化方法
var seller = {};
init(seller);

// 添加订阅人A
seller.listen('显卡',function(msg){
    console.log('我是订阅者A,订阅:显卡,价格为:',msg);
    console.log('\n');
});

// 添加订阅人B
seller.listen('电脑',function(msg){
    console.log('我是订阅者B,订阅:电脑,价格为:',msg);
    console.log('\n');
});
// 添加订阅人C
seller.listen('手机',function(msg){
    console.log('我是订阅者C,订阅:手机,价格为:',msg);
    console.log('\n');
});

// 卖家发布信息并通知相关订阅人
seller.trigger('显卡', 2499);
seller.trigger('棒槌', 2499);
seller.trigger('手机', 999);

总结问题

  • 通过上面的案例,稍微体验了一下封装是什么样的感觉,类似大的插件也是这样的思想,封装对于大厂用途比较多。
  • 尽量的体会过程!!!

深复制 & 浅复制

  • 深复制:深拷贝会开辟新的栈内存,原对象和新对象不共享同一块内存,修改新对象不会影响到原对象。
  • 浅复制:复制指向,引用。
    1. object.assign()
    2. slice
    3. concat

内存

js中,内存是自动分配的,当变量不再需要的时候自动释放,过程如下:

  1. 分配需要的内存空间
  2. 使用分配的内存(读写)
  3. 不需要时释放或者归还 gc(垃圾回收机制)

内存泄露

不再需要此内存,然而由于某种原因,无法释放此内存。

  1. 全局变量带来的
  2. 回调函数
    function a(){
    return 2;
    }
    var b = a()
  3. 额外的定时器
  4. dom引用(removeChild后,还能获得节点的信息)
  5. 闭包也会出现内存泄漏(优点是防止全局变量污染)

垃圾回收机制 GC

垃圾回收的方法分两种,

  1. 引用计数:统计被引用的次数,次数为0,被回收。
  2. 标记清除

分类

  • 栈:用来存放基本数据类型,还有指向复杂数据类型的引用指针
  • 堆:用来存放复杂数据类型,这种数据结构是一种无序的树状,通过key来保存指针,类似字典。
  • 队列:先进先出,典型的例子是 JS中的事件循环(eventsloop

this**

我的this详解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值