实验:扩展本机对象
Experiment: extending a native object
我正在阅读一些关于在javascript中扩展本机对象的讨论。在当前浏览器中扩展本机对象似乎比以前少得多的缺点。当然,考虑到我们对如何通过以下方法扩展对象有更多的控制:
Object.defineProperty(<some parameters...>)
然而,仍然存在的一个很大风险是不同代码/库之间的冲突,从而导致意外行为。
命名冲突(和全局破坏(的风险可以通过命名自己的函数来降低。所以我想如果我们扩展本机对象,为什么我们不这样做呢?当然,执行上下文是一个问题,但我们可以使用 bind(( 来解决这个问题,使该对象的本机函数在我们的扩展功能中可用。所以我创建了以下内容来扩展 Element 对象:
// Define the extend function
Object.defineProperty(Element.prototype, 'extend', { value: function(namespace, object) {
var cache = {};
// Create the namespace and make sure on invocation the Element is bound
Object.defineProperty(Element.prototype, namespace, { value: function() {
var objectCheck = typeof cache[Element.prototype.constructor.name] !== 'undefined';
if(objectCheck && typeof cache[Element.prototype.constructor.name][namespace] !== 'undefined'){
console.log('cache used');
return cache[Element.prototype.constructor.name][namespace];
} else {
var extended = Element.prototype[namespace].extended;
for (var e in extended) {
extended[e] = extended[e].bind(this);
}
if(!objectCheck)
cache[Element.prototype.constructor.name] = {};
cache[Element.prototype.constructor.name][namespace] = extended;
}
return extended;
}});
this[namespace].extended = object;
return this;
}});
// Extend the Element prototype with an attr function in
// the namespace 'namespace' or ofcourse whatever function
Element.prototype.extend('namespace',{
attr: function(name, value) {
if(arguments.length === 1) {
return this.getAttribute(name);
} else {
this.setAttribute(name, value);
return this;
}
}
});
在实际元素上检查它时,一切看起来都不错,命名空间就在那里,在其中我们找到了我们的"attr"函数。我们可以像这样调用它:
document.querySelector('.a-css-class').namespace().attr('class')
// returns 'a-css-class'
代码可以进一步重构,以动态扩展各种对象。但是我很好奇,这对性能意味着什么,这个实验有意义吗?主要问题是,这比直接扩展更好吗?
编辑(基于Bergi对性能的评论(:
可以将创建的函数缓存在外部函数中。让我们看看我是否可以提出一个实现。
编辑2:
添加了一个简单的缓存函数,以确保并非所有命名空间方法都创建每个 en 每次调用。
编辑3:
更新的代码。为了使扩展本机对象更安全,生成了以下代码。它可能会防止命名冲突。谢谢@Bergi:
/**
* Extend a (NATIVE) object with a namespace. See below for an example
*/
Object.defineProperty(Object.prototype, 'extend', { value: function(namespace, object) {
function Wrapper(that) {
this.that = that;
}
Wrapper.prototype = object;
Object.defineProperty(Object.prototype, namespace, { value: function() {
return new Wrapper(this);
}});
}});
// This example uses the Element object, but it could be any object
Element.prototype.extend('namespace',{
attr: function(name, value) {
if(arguments.length === 1) {
return this.that.getAttribute(name);
} else {
this.that.setAttribute(name, value);
return this;
}
}
});
但是我很好奇,这对性能意味着什么
您当前的代码意味着,无论何时调用 namespace()
,您都会创建一个新对象和许多绑定函数,这将严重影响大型命名空间的性能。
我建议让你的namespace
方法返回一个带有 element: this
属性的包装器对象,该对象继承了可以对其调用的所有方法。然后你会使用this.element.getAttribute
而不是this.getAttribute
:
Element.prototype.extend = function(namespace, object) {
function Wrapper(el) {
this.element = el;
}
Wrapper.prototype = object;
Element.prototype[namespace] = function() {
return new Wrapper(this);
};
};
主要问题是,这比直接扩展更好吗?
不多。您仍然在Element.prototype
上定义extend
和namespace
属性,对于这两个属性,所有反对扩展 DOM 的参数仍然有效。您可能会降低与更常用名称 ( attr
( 发生冲突的风险,但这并不比仅定义namespace_attr
方法更好。
- 如何创建行为类似于本机对象的对象
- 如何在javascript中检测本机浏览器/引擎对象
- TypeError:对象函数Object(){〔本机代码〕}没有方法'方法'
- 使用方法和属性定义javascript对象的最佳方法是什么?(如果可能以本机方式)
- 调用本机原型方法时扩展或继承对象原型
- 在 JavaScript 中依赖全局本机对象是否安全,尤其是 Object 对象
- 我怎么知道本机 JS 对象没有被篡改
- 将本机数组/对象转换为 Ember.Array/Ember.Object 的最佳实践
- 对象函数 Date() { [本机代码] } 在 Chrome 中使用 Date.js 时没有方法“compareTo”
- 通过带有对象子级的数组进行 React 本机映射 - 工作方式与在 react web 中不同
- 如何在 nodejs 中全局添加方法到 JSON、Date 或其他“本机”对象
- 使用原型来扩展本机对象不好
- 渲染时,未定义不是React本机中的对象
- 将本机浏览器事件对象转换为jQuery事件对象
- JavaScript:主机对象也是本机对象的示例是什么
- 在本机错误对象调用函数's结构
- 有没有一种方法可以在javascript中隔离本机对象扩展
- 实验:扩展本机对象
- 如何覆盖javascript本机对象的内置方法
- 本机事件对象的自定义方法