本文已参与「 新人创作礼 」活动,一起开启掘金创作之路
昨天关于实现一个intanceof 是通过链式查找prototype的比对。
其中一个非常重要的方法就是。Object.getPrototypeOf
当然这个方法目前几乎我们不用去考虑兼容性,ie9 以上都对这个方法进行了支持。
chrome就不用说了,其他暂时忽略。
Object.setPrototypeOf()是ECMAScript 6最新草案中的方法,相对于Object.prototype.__proto__
如果这么理解起来是不是很难在实际工作中应用起来。
关于前端JS继承的方式那是提多了,有class方式,组合 prototype的方式,Object.create。但是今天的主角是 setPrototypeOf。
simple Demo:
function fn(name) {
this.name = name;
}
fn.prototype.sayName = function () {
return this.name;
}
let obj = {}
Object.setPrototypeOf(obj,fn.prototype);
fn.call(obj , 'cc');
console.log (obj.name);
console.log (obj.sayName());
这样组合起来不是更加觉得亲切。
chrome 版本字2014年的版本就支持了setPrototypeOf
如果在这个之前我们改如何使用呢, 我这里并不是让大家去造轮子,只是借用这个方法,让大家更深刻了解setPrototypeOf 的真正实现而已。
if (!Object.setPrototypeOf) {
// 仅适用于Chrome和FireFox,在IE中不工作:
Object.prototype.setPrototypeOf = function(obj, proto) {
if(obj.__proto__) {
obj.__proto__ = proto;
return obj;
} else {
// 如果你想返回 prototype of Object.create(null):
var Fn = function() {
for (var key in obj) {
Object.defineProperty(this, key, {
value: obj[key],
});
}
};
Fn.prototype = proto;
return new Fn();
}
}
}
这段代码来自 : 查看mozilla
主要还是通过__proto__的肤质操作。
如果发现obj部位构造,那就在自定义的function ,然后通过defineProperty进行属性绑定。defineProperty属性其实功能超级超大,例如数据监听等。最早期的MVVM MV框架有些就是依赖这些底层方法实现的。
还有一些继承的最后经过babel转译也是通过defineProperty。
"use strict";
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Parent = function () {
function Parent(name, age) {
_classCallCheck(this, Parent);
this.name = name;
this.age = age;
}
_createClass(Parent, [{
key: "speakSomething",
value: function speakSomething() {
console.log("I can speek chinese");
}
}]);
return Parent;
}();
这个一个类构造通过babel转译后的代码。
仔细看这个代码还是非常的有意思,其实通过es6的类构造的代码非常之少。
class Parent {
constructor(name,age){
this.name = name;
this.age = age;
}
speakSomething(){
console.log("I can speek chinese");
}
}
这就是前端babel转译的魅力了。
今天先到这里,困了,明天继续分享。