深入理解JavaScript Object.defineProperty——不修改引擎代码自定义Egret组件代码

深入理解JavaScript Object.defineProperty

不修改引擎代码自定义Egret组件代码

 

需求描述:

开发微信小游戏,大多存在“获取昵称头像”需要用户同意授权的交互,如果用户同意则游戏中使用微信返回的头像地址,如果不同意获取头像失败,则服务器给它随机1个虚拟头像: http://cdn.xxxxxx.com/project/img/avatar/head/1.jpg(1是1-10000中随机出来的)
这是1个很长且可能变化的地址,为了更好的灵活性和减少服务器存储空间,数据库我们想只存1个id,而不是整个url图片路径,把域名文件夹路径配置在外部。

需求实现1:

通常情况下,我们会这样处理,在业务代码处针对头像地址分别分别判断:

var img:eui.Image;
var headurl = userinfo.headurl;//用户存储的头像地址(有可能是完整的微信头像地址,也有可能是服务器构造的id)
if(!isNaN(headurl)){
   img.source = "http://cdn.xxxxxx.com/project/img/avatar/head/" + headurl + ".jpg";
}
else{
   img.source = headurl;
}

如果很多地方都需要显示用户的头像,那么这样重复性的代码就会分布在很多地方,这不是好的代码编写习惯。
有同学就说了,可以把这个代码封装成1个方法,以供需要的地方调用

fuction setImgSource(img, headurl){
	if(!isNaN(headurl)){
	   img.source = "http://cdn.xxxxxx.com/project/img/avatar/head/" + headurl + ".jpg";
	}
	else{
	   img.source = headurl;
	}
}
setImgSource(img, userinfo.headurl);

这样在显示头像地址的地方只需要添加1行代码,的确比较简单,但是不可否认的是很容易遗漏。

这里提供另一种思路,重写Egret引擎的source方法,当然不是去修改引擎代码文件(可以但不建议),见下面需求实现2.

需求实现2:

在不修改引擎代码文件的基础上如何重写代码呢? 那就是使用 Object.defineProperty 方法
Object.defineProperty的用法是:

Object.defineProperty(person,'name',{
    configurable:false, //能否使用delete、能否需改属性特性、或能否修改访问器属性、,false为不可重新定义,默认值为true
    enumerable:false, //对象属性是否可通过for-in循环,flase为不可循环,默认值为true
    writable:false, //对象属性是否可修改,flase为不可修改,默认值为true
    value:0 //对象属性的默认值,默认值为undefined
});

回到本题的需求,在项目启动的时候执行如下代码

let rootURL = "http://cdn.xxxxxx.com/project/img/avatar/head/";
        Object.defineProperty(eui.Image.prototype, "source", {
            get: function () {
                return this._source;
            },
            set: function (value) {
                if (value == this._source) {
                    return;
                }
                if(value && !isNaN(value)){ //如果是数字,表示是虚拟头像,需要构造头像路径
                    value = rootURL + value + ".jpg";
                }
                this._source = value;
                if (this.$stage) {
                    this.parseSource();
                }
                else {
                    this.sourceChanged = true;
                    this.invalidateProperties();
                }
            },
            enumerable: true,
            configurable: true
        });

这样就完美解决了这个需求。

扩展思考:

Object.defineProperty 能定义 enumerable属性,这个属性作用是设置对象属性是否可通过for-in循环,flase为不可循环,默认值为true
我们试试这段代码

var date = new Date();
for(var key in date){ 
    console.log(key);
}
输出是 undefined

因此可以得出结论,JavaScript的Date对象是设置了 enumerable属性是 false,从而避免对外暴露该对象的具体方法和属性。

参考文章:https://blog.csdn.net/qq_17335153/article/details/52584727

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星星之Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值