我正在尝试独立地在不同区域运行我的JS代码,所以我想创建一个类并找到这个article我的问题是,我不能使用我班上的函数在我班上。
这是我的JS代码:
window.addEventListener('load', tagEditorsInit);
function tagEditorsInit() {
var tagEditors;
var tagLists = document.getElementsByClassName('tagList');
for(var i = 0; i < tagLists.length; i++) {
tagEditors[i] = new function() {
var edit, editTag, tagList, tagInput, tagOutput, i;
this.init = new function() {
edit = false;
tagList = document.querySelectorAll('[class=tagList]').item(i); //L.96/97 #1
tagInput = tagList.querySelectorAll('[name=tagInput]');
tagOutput = tagList.querySelectorAll('[name=tags]');
tagInput.addEventListener('keyup', tagOnKeyPress(event.keyCode)); //13-ERROR
tagList.addEventListener('mouseout', function() {if(tagList.ownerDocument.activeElement.parentNode !== tagList && !isHover(tagList)) {tagList.style.maxHeight = '40px';}});
tagInput.addEventListener('focus', changeSize);
tagInput.addEventListener('blur', changeSize);
for(var i = 2; i < tagList.childNodes.length; i++) {
tagList.childNodes[i].addEventListener('click', tagOnClick);
tagList.childNodes[i].addEventListener('mousemove', tagOnMouseMove);
tagList.childNodes[i].addEventListener('mouseout', tagOnMouseOut);
}
};
this.tagOnKeyPress = new function(keyCode) {
var tagInputValue = tagInput.value.trim();
if(tagInputValue.length !== 0) {
if(edit) {
if(keyCode === 13) {
edit = false;
editTag.style.borderColor = '#ddd';
tagInput.value = '';
return;
}
tagOutput.value = tagOutput.value.replace(editTag.innerHTML,tagInputValue);
newTag = editTag;
} else {
if(keyCode !== 13) return;
tagOutput.value = tagOutput.value + tagInputValue + ';';
var newTag = document.createElement('div');
newTag.addEventListener('click', tagOnClick);
newTag.addEventListener('mousemove', tagOnMouseMove);
newTag.addEventListener('mouseout', tagOnMouseOut);
}
newTag.innerHTML = tagInputValue;
tagList.appendChild(newTag);
}
if(!edit) tagInput.value = '';
};
this.tagOnClick = new function() {
if((this.offsetWidth + getOffsetLeft(this) - event.pageX) < parseInt(this.style.backgroundSize, 10)) {
tagOutput.value = tagOutput.value.replace(this.innerHTML + ';','');
this.parentNode.removeChild(this);
tagInput.value = '';
edit = false;
} else {
setEdit(this);
}
tagInput.focus();
};
this.tagOnMouseMove = new function() {
if((this.offsetWidth + getOffsetLeft(this) - event.pageX) < parseInt(this.style.backgroundSize, 10)) {
this.style.backgroundSize = '16px';
} else {
this.style.backgroundSize = '18px';
}
};
this.tagOnMouseOut = new function() {
this.style.backgroundSize = '18px';
};
this.setEdit = new function(tag) {
edit = true;
editTag = tag;
tag.style.borderColor = '#297CCF';
tagInput.value = tag.innerHTML;
};
this.changeSize = new function(e) {
if(e.type === 'focus') {
tagList.style.maxHeight = 'none';
} else if(e.type === 'blur' && !isHover(tagList)) {
tagList.style.maxHeight = '40px';
}
};
this.isHover = new function(elem) {
return (elem.parentElement.querySelector(':hover') === elem);
};
this.getOffsetLeft = new function(elem) {
var offsetLeft = 0;
while(true) { //521px over while scrolling to the right ---> (-TABLE:521px)
if(elem.nodeName !== 'TABLE') offsetLeft += elem.offsetLeft;
elem = elem.parentNode;
if(elem.nodeName === 'HTML') break;
}
return offsetLeft;
};
};
//tagEditors[i].tagList = tagLists.item(i); Why isn't it working??? #1
tagEditors[i].i = i;
tagEditors[i].init();
}
}
我收到此错误消息:
13:未捕获的ReferenceError:未定义tagOnKeyPress
13 :(匿名函数)
8 :(匿名函数)
6:tagEditorsInit
问题:
谢谢! - Minding
答案 0 :(得分:3)
调用以this
开头的函数,该函数引用当前范围(在本例中,是&#34;类&#34的对象;您创建的,这是tagOnKeyPress
函数的位置定义)。
tagInput.addEventListener('keyup', this.tagOnKeyPress(event.keyCode));
请注意,您的代码中还有其他函数调用也需要进行此更改。
这是一个从对象内部调用对象函数的简单示例:
function MyClass() {
this.firstFunc = function() {
console.log('first function');
};
this.secondFunc = function() {
console.log('second function calls:');
this.firstFunc();
};
};
var obj = new MyClass();
obj.firstFunc();
obj.secondFunc();
&#13;
如果查看控制台,您将看到以下输出:
第一个功能
第二个函数调用:
第一个功能
答案 1 :(得分:1)
原型方式:
function MyClass(arg1, arg2) {
this.prop = arg1
this.prop2 = arg2
}
MyClass.prototype.myFcuntion = function() {
this.prop = 'changed prop';
}
MyClass.prototype.property12 = 'some property'
var instance = new MyClass('property1', 'property2');
instance.prop; // return string 'property1'
instance.myFunction();
instance.prop; // return string 'changed prop'
答案 2 :(得分:1)
好的,先解决几件事:
1.这不是创建对象的理想方法,这是您要做的事情。在这个例子中,我对它进行了一些修改,但我仍然会使用原型方法重写它。你在这里所拥有的将为每个对象实例创建这些函数,加载方式比你需要的更多。
2.在带有onKeyPress的textareas中,您不能引用tagOnKeyPress函数,该函数是tagEditor对象的一部分。它没有在公共范围内定义。
3.添加eventListeners时,除非您将函数作为处理程序返回,否则不要在处理程序的定义中执行该函数。
tagInput.addEventListener('keyup', tagOnKeyPress(event.which));
尝试执行&#34; tagOnKeyPress&#34; immediatley。相反,只传递函数引用,并期望&#34;事件&#34;传递给它的类型。然后,在函数中定义keyCode。
tagInput.addEventListener('keyup', this.tagOnKeyPress); //13-ERROR
this.tagOnKeyPress = function(event) {
var keyCode = event.which;
}
4.正如其他人所指出的,当你引用函数范围内定义的函数(你的对象)时,你需要使用&#34;这个&#34;作为前缀。
我稍微更改了代码以定义&#34; TagEditor&#34;用于循环的对象。您可以将这些函数添加到TagEditor原型中,以提高性能和可扩展性。
代码:
var TagEditor = function () {
var edit, editTag, tagList, tagInput, tagOutput, i;
this.init = function () {
edit = false;
tagList = document.querySelectorAll('[class=tagList]').item(i); //L.96/97 #1
tagInput = tagList.querySelectorAll('[name=tagInput]')[0];
tagOutput = tagList.querySelectorAll('[name=tags]');
tagList.addEventListener('mouseout', function () { if (tagList.ownerDocument.activeElement.parentNode !== tagList && !isHover(tagList)) { tagList.style.maxHeight = '40px'; } });
tagInput.addEventListener('keyup', this.tagOnKeyPress); //13-ERROR
tagInput.addEventListener('focus', this.changeSize);
tagInput.addEventListener('blur', this.changeSize);
for (var i = 2; i < tagList.childNodes.length; i++) {
tagList.childNodes[i].addEventListener('click', this.tagOnClick);
tagList.childNodes[i].addEventListener('mousemove', this.tagOnMouseMove);
tagList.childNodes[i].addEventListener('mouseout', this.tagOnMouseOut);
}
};
this.tagOnKeyPress = function (e) {
var keyCode = e.which;
var tagInputValue = tagInput.value.trim();
if (tagInputValue.length !== 0) {
if (edit) {
if (keyCode === 13) {
edit = false;
editTag.style.borderColor = '#ddd';
tagInput.value = '';
return;
}
tagOutput.value = tagOutput.value.replace(editTag.innerHTML, tagInputValue);
newTag = editTag;
} else {
if (keyCode !== 13) return;
tagOutput.value = tagOutput.value + tagInputValue + ';';
var newTag = document.createElement('div');
newTag.addEventListener('click', tagOnClick);
newTag.addEventListener('mousemove', tagOnMouseMove);
newTag.addEventListener('mouseout', tagOnMouseOut);
}
newTag.innerHTML = tagInputValue;
tagList.appendChild(newTag);
}
if (!edit) tagInput.value = '';
};
this.tagOnClick = function () {
if ((this.offsetWidth + getOffsetLeft(this) - event.pageX) < parseInt(this.style.backgroundSize, 10)) {
tagOutput.value = tagOutput.value.replace(this.innerHTML + ';', '');
this.parentNode.removeChild(this);
tagInput.value = '';
edit = false;
} else {
setEdit(this);
}
tagInput.focus();
};
this.tagOnMouseMove = function () {
if ((this.offsetWidth + getOffsetLeft(this) - event.pageX) < parseInt(this.style.backgroundSize, 10)) {
this.style.backgroundSize = '16px';
} else {
this.style.backgroundSize = '18px';
}
};
this.tagOnMouseOut = function () {
this.style.backgroundSize = '18px';
};
this.setEdit = function (tag) {
edit = true;
editTag = tag;
tag.style.borderColor = '#297CCF';
tagInput.value = tag.innerHTML;
};
this.changeSize = function (e) {
if (e.type === 'focus') {
tagList.style.maxHeight = 'none';
} else if (e.type === 'blur' && !isHover(tagList)) {
tagList.style.maxHeight = '40px';
}
};
this.isHover = function (elem) {
return (elem.parentElement.querySelector(':hover') === elem);
};
this.getOffsetLeft = function (elem) {
var offsetLeft = 0;
while (true) { //521px over while scrolling to the right ---> (-TABLE:521px)
if (elem.nodeName !== 'TABLE') offsetLeft += elem.offsetLeft;
elem = elem.parentNode;
if (elem.nodeName === 'HTML') break;
}
return offsetLeft;
};
};
function tagEditorsInit() {
var tagEditors = [];
var tagLists = document.getElementsByClassName('tagList');
for (var i = 0; i < tagLists.length; i++) {
var tagEditor = new TagEditor();
tagEditor.tagList = tagLists.item(i); // Why isn't it working??? #1
tagEditor.i = i;
tagEditor.init();
tagEditors.push(tagEditor);
}
}
window.addEventListener('load', tagEditorsInit);
现在,我承认我不会在任何地方使用Prototype方法。有时候,我会编写一个我需要在特定实例中使用的小对象,并且我不会像使用复杂对象那样处理它。但是,在编写jQuery插件或自定义应用程序的特殊脚本时,Prototype方法更容易阅读,分解和使用。
这究竟意味着什么?原型方法使用对象类型定义函数,而不是每次创建对象的实例时定义。为了举例说明使用上面的代码,每次创建TagEditor时,该tagEditor对象都会为该特定的tagEditor对象重新定义所有这些函数。如果你能够扩展或打开单个对象,就像阅读为每一个对象定义的所有函数。
使用原型方法,它或多或少基于类,就像C ++或C#这样的面向对象的lang会有。每当你打电话给 &#34; tagOnKeyPress&#34;函数,它使用与TagEditor类型相关联的函数。不是用&#34; tagEditor&#34;定义的那个。 TagEditor类型的对象。简而言之,该函数仅定义一次,并继承对&#34; tagEditor&#34;中定义的属性的访问权限。那种对象。
如果我没有把这个解释与你混淆,请查看这篇MDN文章,该文章很好地展示了所有这些的例子以及它的不同之处:
更新此更新是对您的评论和小提琴的回应。我刚刚通过你的小提琴进行了一些修改。希望你能看到我改变了什么。以下是一些额外的评论
1. this.tagInput的定义需要引用一个节点,而不是NodeList。有几个我认为你期望单个节点但是得到长度为1的NodeList。要引用实际的DOM元素来分配EventListener,你只需要指定NodeList的0索引。
2.当您将函数绑定为处理程序时,除非返回函数,否则不想执行该函数。上面的子弹3显示了一个这样的例子。在函数名称(myMouseHandler())之后添加括号时,它会在此时执行该函数。它不会等到偶数发生。
3.当您在特定范围内工作时,您可以定义局部变量以简化对象属性的使用。例如,如果您使用&#34; this.tagList&#34;很多,你可能厌倦了打字&#34; this.tagList&#34;到处。定义它时,可以像这样分配属性和局部变量:
var tl = this.tagList = document.getElementsByClassName('tagList').item(tagListID);
然后你可以使用&#34; tl&#34;在该范围内。
this.tagOuput.value = tl.value;
4.使用Prototype分配事件处理程序时,您仍然需要一种方法来引用您正在使用的主对象。 eventListener绑定中的匿名函数提供了一种在需要时执行此操作的简便方法。
// function is the actual handler. e = event, this = element, te = tagEditor
tagInput.addEventListener('mouseout', function(e) { te.tagOnClick(e, this); });
我试着清理你的小提琴并开始工作,我猜你正在尝试。您可能需要更多,但这可能为您提供更清晰的工作位置。