将__proto__值从一个对象复制到另一个对象的正确方法

时间:2015-11-19 14:24:00

标签: javascript jquery prototype

我在工作中有这个微库,就像一个轻量级的jQuery(让我们称之为kQuery)。

以下是一些删节代码:

(function(_){

    var dom_obj,
        ret_obj;

    var kQuery = function(selector, context, undefined){
        dom_obj = new Dom(selector, context, undefined);
        ret_obj = dom_obj.core;
        ret_obj.__proto__ = dom_obj.constructor.prototype;

        return ret_obj;
    };

    function Dom(selector, context, undefined)
    {
        var el;
        el = document.querySelectorAll(selector);

        this.core = [];
        var payload = (_.count(el) === 1) ? el[0] : el;
        this.core.push(payload);
        this.core.context = window.document;
        this.core.selector = selector;
    }

    Dom.prototype.each = function(callback){
        //my each method code
    };

    Dom.prototype.find = function(selector) 
    {
        //my find method code
    };

    Dom.prototype.addClass = function(class_name) 
    {
        //my addClass method code
    };

    //assign to window object
    window.kQuery = kQuery;

    //assign to $ namespace if it is undefined
    window.$ = window.$ || window.kQuery;

})(_);

注意:_不是下划线,只是非常相似的东西。

上面的代码有效[并且通过工作,我的意思是它创建了一个类似于数组的对象,非常类似于jQuery创建的对象,例如: $('#element_id'))],但我已经读过使用__proto__这种方式可能不是最好的(反模式而不是跨浏览器)。

是否有另一种方法可以在跨浏览器[ie8基线]方式中重写ret_obj.__proto__ = dom_obj.constructor.prototype;

4 个答案:

答案 0 :(得分:1)

在这种情况下,您应该使用Object.create

ret_obj = Object.create(dom_obj.constructor.prototype, dom_obj.core)

答案 1 :(得分:1)

我看到你能做到这一点的唯一方法是在IE 8中创建一个新的Object(使用new运算符),然后在构造函数中将dom_obj.core的属性赋值给它: / p>

var kQuery = function(selector, context, undefined){
    dom_obj = new Dom(selector, context, undefined);

    function ret_obj_proto (domob) {
        for(var item in domob) {
            if(Object.prototype.hasOwnProperty.call(domob, item)) { // Check if it is an own property, IE 8 style
                this[item] = domob[item];
            }
        }
    };

    ret_obj_proto.prototype = dom_obj.constructor.prototype;
    ret_obj = new ret_obj_proto(dom_obj);

    return ret_obj;
};

我很好奇是否有更好的解决方案。

答案 2 :(得分:0)

如果您在ES6环境中,请使用Object.setPrototypeOf

Object.setPrototypeOf(ret_obj, dom_obj.constructor.prototype)

Compatibility table

答案 3 :(得分:0)

我能够解决这个问题:

{{ form_widget(form.timespan, {'attr': {'class': 'span2'}}) }}

一旦对象已经创建,改变(function(_){ if (!Object.create) { Object.create = function(o, properties) { if (typeof o !== 'object' && typeof o !== 'function') { throw new TypeError('Object prototype may only be an Object: ' + o); } else if (o === null) { throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument."); } /*jshint -W116 */ if (typeof properties != 'undefined') { throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument."); } /*jshint +W116 */ function F() {} F.prototype = o; return new F(); }; } function merge( first, second ) { var len = +second.length, j = 0, i = first.length; while ( j < len ) { first[ i++ ] = second[ j++ ]; } // Support: IE<9 // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) if ( len !== len ) { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; } var init_dom_obj, dom_obj; var kQuery = function(selector, context, undefined){ init_dom_obj = new initDom(selector, context, undefined); dom_obj = new Dom(); dom_obj = merge(dom_obj, init_dom_obj.core); dom_obj.context = init_dom_obj.context; dom_obj.selector = init_dom_obj.selector; return dom_obj; }; function Dom(){} Dom.prototype = Object.create(Array.prototype); function initDom(selector, context, undefined) { var el; el = document.querySelectorAll(selector); this.core = []; var payload = (_.count(el) === 1) ? el[0] : el; this.core.push(payload); this.context = window.document; this.selector = selector; } Dom.prototype.each = function(callback){ //my each method code }; Dom.prototype.find = function(selector) { //my find method code }; Dom.prototype.addClass = function(class_name) { //my addClass method code }; //assign to window object window.kQuery = kQuery; //assign to $ namespace if it is undefined window.$ = window.$ || window.kQuery; })(_); [我最初尝试这样做的方式]是有问题的,我认为以迂回方式做事情会更好:

  1. 将初始构造函数移动到不同的函数/对象空间[&#39; initDom&#39;]并使用它来托管所选对象
  2. 使用类似于数组的结构创建主对象[__proto__]以及来自get-go的所有必需方法
  3. 将所选对象[Dom]与我们的主init_dom_obj.core对象合并(可行,因为它们都是数组)
  4. 手动恢复丢失的对象属性[由于合并操作而丢失]
  5. 希望如果您正在构建一个微型库或类似的东西,这会有所帮助。