我希望实现以下目标。
HTMLSpanElement.prototype.testNS = {
_this: this,
testFunc: function() {
console.log(this.innerHTML) //undefined as expected as this is the testFunc object
},
testFunc2: function() {
console.log(this._this) //Window object
}
}
我的目标是在这种情况下直接向span元素添加一些辅助函数。
所以,如果我有以下内容:
<span>test</span>
我可以找到span并调用此代码返回“test”
spanElement.testNS.testFunc()
我知道当我这么做时,一个函数会保留它的父级范围......
HTMLSpanElement.prototype.testFunc = function() {
console.log(this.innerHTML)
}
但是我试图稍微组织一下代码,并且当我添加它们时,函数来自哪里更明显,当我做一个普通的JSON对象时,我似乎找不到保留范围的方法将此范围抓取到_this: this
它只返回“窗口”的全局范围。
答案 0 :(得分:3)
免责声明:您不应该尝试修改内置类型的原型,尤其是宿主对象。这是一个坏主意。
您的方法不适合您的原因是使用testNS
对象作为this
调用函数。
如果使用testNS
将Object.defineProperty
定义为具有getter函数的属性,则可以使此工作正常。这样做的原因是get
函数在访问属性的对象的上下文中运行(这将是跨度):
Object.defineProperty(HTMLSpanElement.prototype, 'testNS', {
get: function() {
var _this = this;
return {
testFunc: function() {
console.log(_this.innerHTML)
},
testFunc2: function() {
console.log(_this)
}
}
}
});
var span = document.getElementById('mySpan');
span.testNS.testFunc();
span.testNS.testFunc2();
<span id="mySpan">Wah-hoo!</span>
更“流露”的方法是让testNS
成为普通函数并将其称为一个函数。这是有效的,因为testNS
在被调用它的对象的上下文中被调用(再次,跨度):
HTMLSpanElement.prototype.testNS = function() {
var _this = this;
return {
testFunc: function() {
console.log(_this.innerHTML)
},
testFunc2: function() {
console.log(_this)
}
}
}
var span = document.getElementById('mySpan');
span.testNS().testFunc();
span.testNS().testFunc2();
<span id="mySpan">Wah-hoo!</span>
答案 1 :(得分:1)
当您将某个功能称为foo.bar()
时,this
内的bar
会引用foo
。因此,如果您将该功能称为spanElement.testNS.testFunc()
,则this
会引用spanElement.testNS
。
_this: this,
无效,因为this
无法引用<span>
元素。
要从spanElement
访问testFunc
,您可以将testNS
实施为获取者:
Object.defineProperty(HTMLSpanElement.prototype, 'testNS', {
get: function() {
var element = this;
return {
testFunc: function() {
console.log(element.innerHTML);
},
};
},
});
document.querySelector('span').testNS.testFunc();
&#13;
<span>foo</span>
&#13;
答案 2 :(得分:0)
因为这是一个奇怪的要求,我写了一个相当奇怪的解决方案:-)
基本上,createElement已被覆盖,以便添加命名空间对象文字,然后使用绑定到函数的元素实例在命名空间顶部定义新函数testFunc
!function(){
var defaultNamespace = "testNS";
var createElement = document.createElement;
document.createElement = function(tag, namespace) {
var element = createElement.apply(document, arguments);
element[namespace || defaultNamespace] = {
testFunc : function() {
console.log(this.innerHTML);
}.bind(element)
};
return element;
}
}();
var span = document.createElement("span");