Javascript 将_proto__值从一个对象复制到另一个对象的正确方法
我在工作中有一个微型库,它就像一个轻量级jQuery(我们称之为kQuery) 以下是一些节略代码: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;
(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;
})(_);