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

Javascript 将_proto__值从一个对象复制到另一个对象的正确方法,javascript,jquery,prototype,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;

我在工作中有一个微型库,它就像一个轻量级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;

})(_);
注意:
\u
不是下划线,只是一些非常相似的东西

上面的代码是有效的[我所说的有效,是指它创建了一个类似数组的对象,与jQuery创建的对象非常相似,例如
$(“#element_id')
),但我已经读到,使用
\u proto_
这种方式可能不是最好的(反模式,而不是跨浏览器)


是否有另一种方法重写
ret_obj.\uu proto\uuu=dom_obj.constructor.prototype以跨浏览器[ie8基线]的方式?

您应该使用
对象。在此实例中创建

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

如果您在ES6环境中,请使用:


我认为您可以这样做的唯一方法是在IE 8中创建一个新对象(使用
new
操作符),然后在构造函数中将
dom_obj.core
的属性分配给它:

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;
};

我很好奇是否有更好的解决办法。

我能够解决这个问题:

(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;

})(_);
(函数(){
如果(!Object.create)
{
Object.create=函数(o,属性)
{
如果(o的类型=='对象'&&o的类型=='功能')
{
抛出新的TypeError('对象原型只能是对象:'+o);
}
else如果(o==null)
{
抛出新错误(“此浏览器的Object.create实现是一个垫片,不支持将'null'作为第一个参数。”);
}
/*jshint-W116*/
如果(属性类型!=“未定义”)
{
抛出新错误(“此浏览器的Object.create实现是一个垫片,不支持第二个参数。”);
}
/*jshint+W116*/
函数F(){}
F.原型=o;
返回新的F();
};
}
函数合并(第一,第二)
{
变量len=+second.length,
j=0,
i=第一个长度;
而(j//支持:IE8我刚刚注意到了IE8的部分。我将把这个答案留在这里,以防它对其他人有帮助。不幸的是IE8没有
对象。创建
。我得到一个错误
未捕获的类型错误:属性描述必须是一个对象:
。我想这是因为
dom\u obj.core
是一个数组。@joews如果它不支持ES5,只需创建一个构造函数,将原型设置为
dom_obj.constructor.prototype
@obinwanehill为什么要更改数组的原型?这是一个巨大的代码味道!@obinwanehill哪一部分特别重要?基本上,您希望它如何工作?我提到了重新编写数组原型的代码味道,因为数组的作用是作为一个列表。如果你想对它们执行特定的操作,那么你可以使用函数,但尽量避免重新编写数组的原型以避免不必要的副作用。重写它的原型意味着你不能使用任何内置数组方法(这意味着它不再是数组)谢谢。这并不是我想要的结果;我希望它和JQuery一样,我的初始解决方案除了
\uuuuuu proto\uuuuuu
之外都能做到。我一直在看JQuery的代码,但不太明白他们是如何让它工作的结果出了什么问题(具体说明会有所帮助)另外,为什么需要从
Dom
中创建一个单独的返回对象?难道不能只返回
Dom\u obj
?PS:JQuery只返回一个名为
init
的内部函数的新实例:
return new JQuery.fn.init(选择器,上下文)
不涉及
\uuuuu proto\uuuuuu
。如果您使用Chrome开发工具,您可能会更清楚地了解我所指的内容。如果您使用JQuery检查对象,例如
console.log($(“#某些元素”))
您会注意到类似数组的结构不同于类似对象的结构。
dom_obj
有我需要的,但我想将
dom_obj.core
的内容提升到主要对象级别(而不是将其作为属性)并保持一个类似数组的结构,而不丢失
\uuuu proto\uuuu
中的值……这可能吗?jQuery返回一个常规对象,其中数字作为其元素的索引。
$('.topbar icon');
返回DOM引用的以下对象:
对象{0:,1:,2:,长度:3,prevObject:Object,上下文:HTMLDocument→ 33808753,选择器:“.topbar icon”}
您不需要
\uuu proto\uuu
来创建这样的对象。在您的Dom构造函数中,不要将其分配给
this.core
…只需将其分配给
this
(例如
this[0]=payload[0]
)的数字索引即可。如果使用循环,您可以自动执行此操作。
(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;

})(_);