Object.assign的替代方案:兼容Safari且保留对象继承关系
解决Safari中Object.assign兼容问题,保留原型继承且避免手动赋值混乱
嘿,我来帮你搞定这个问题!首先得澄清一个小误区:你写的目标代码var stuff = Object.create(shared); stuff = {//stuff };其实是有问题的——第二行直接把stuff重新赋值成了一个新的普通对象,完全丢失了和shared的原型继承关系,咱们要的应该是把自定义属性挂载到继承自shared的对象上,而不是替换整个对象。
接下来针对你的需求(不依赖Babel、兼容老Safari、保留继承、避免逐个赋值混乱),给你两个简单好用的方案:
方案一:原生循环复制属性(极简版)
直接用原生的for-in循环把自定义属性复制到已创建的继承对象上,所有浏览器(包括老版Safari)都支持,而且性能拉满,不会给卡顿的网站添负担:
var shared = { foo: 'bar' }; // 先创建继承自shared的对象,原型链保留 var stuff = Object.create(shared); // 把需要添加的属性统一放在一个对象里 var customStuff = { name: 'myStuff', logShared: function() { console.log(this.foo); // 能访问到shared的属性,继承生效 } }; // 循环复制属性到stuff上 for (var key in customStuff) { // 只复制自身可枚举属性,和Object.assign行为一致 if (customStuff.hasOwnProperty(key)) { stuff[key] = customStuff[key]; } }
方案二:封装成复用函数(更简洁)
如果需要多次用到这种逻辑,可以把复制逻辑封装成一个小函数,用法和Object.assign几乎一样,完全无依赖:
// 封装一个极简的属性复制函数 function extend(target, source) { for (var key in source) { if (source.hasOwnProperty(key)) { target[key] = source[key]; } } return target; } // 使用起来就很清爽了 var shared = { foo: 'bar' }; var stuff = extend(Object.create(shared), { name: 'myStuff', logShared: function() { console.log(this.foo); } });
为什么这两个方案可行?
- 兼容性拉满:for-in循环和hasOwnProperty是ES3就支持的特性,老Safari完全没问题;
- 保留继承:先通过Object.create建立原型链,再复制属性,不会破坏继承关系;
- 避免代码混乱:所有自定义属性都放在一个对象里,不需要逐个写
stuff.key = value; - 性能友好:没有多余的库或转译代码,不会加重网站卡顿的情况。
内容的提问来源于stack exchange,提问作者Magdi Gamal
相关产品推荐
相关产品推荐

