javascript 'this' 链接代码
javascript 'this' code for chaining
我正在尝试开发一个类似于 jQuery 的允许链接的库。我已经有了可用的函数,但我需要将它们链接在一起。请查看下面的代码并帮助我解决如何使用 'this' 访问正确的上下文并开发一个允许链接的类似于 jQuery 的库。我希望 'learnQuery()' 的功能类似于 jQuery()。我在将 cssClass 方法链接在一起时遇到问题。
function learnQuery(elementSelector) {
'use strict';
var learnQueryContext = this;
function cssPropProxy(property, value) {
return cssProp(elementSelector, property, value);
}
function ajaxReqProxy(url, options) {
return ajaxReq(url, options);
}
var cssClass = new CssClass();
return {
cssProp : cssPropProxy,
ajaxReq : ajaxReqProxy,
cssClass: {
add: function(setClass) {
cssClass.add(elementSelector, setClass);
return learnQueryContext;
},
remove: function(deleteClass) {
cssClass.remove(elementSelector, deleteClass);
return learnQueryContext;
},
toggle: function(toggleClass) {
cssClass.toggle(elementSelector, toggleClass);
return learnQueryContext;
},
has: function(hasClass) {
cssClass.has(elementSelector, hasClass);
return learnQueryContext;
}
}
是的,在尝试学习相同的东西之前,我正在玩类似的东西。我还有这个保存所以看看你是否能理解这个:
var $ = (function(){
$ = function(selector){ return new MyQuery(selector); };
var MyQuery = function(selector){
var nodes = document.querySelectorAll(selector);
this.each = Array.prototype.forEach.bind(nodes);
this.map = Array.prototype.map.bind(nodes);
var len = this.length = nodes.length;
for(var i = 0; i < len; i++) this[i] = nodes[i];
};
$.fn = MyQuery.prototype = {
addClass: function(classes){
this.each(function(el){
classes.forEach(function(className){
el.classList.add(className);
});
});
return this;
},
removeClass: function(classes){
this.each(function(el){
classes.forEach(function(className){
el.classList.remove(className);
});
});
return this;
},
addAttribute: function(newAttrib, value){
this.each(function(el){
el.setAttribute(newAttrib, value);
});
return this;
},
removeAttribute: function(attrib, value){
this.each(function(el){
el.removeAttribute(attrib);
});
return this;
},
remove: function(){
this.each(function(el){
el.remove();
});
return this;
},
on: function(type, callback){
this.each(function(el){
el.addEventListener(type, callback);
});
return this;
},
append: function(elem){
this.each(function(el){
el.appendChild(elem);
});
return this;
},
css: function(prop, value){
this.each(function(el){
el.style[prop] = value;
});
return this;
}
}
return $;
})();
很难弄清楚您希望使用这些函数发生什么。
cssPropProxy()
returns cssProp
但 cssProp
看起来只是对 cssPropProxy()
的引用。
链接的基本思想是 return 返回对象实例。在您的代码中,您似乎正在 return 引用该函数。这是一个可能有帮助的简单链接示例:
function chainingExample(startText){
return {
mytext: startText,
append: function(text){
this.mytext += text;
return this;
},
show: function(){
return this.mytext;
}
}
}
console.log(chainingExample("hello").append(" there").append(" again").show());
/* results in: "hello there again" */
以这种方式使用时 this
指向回 returned 对象。它看起来像:
{ mytext: 'hello there again',
append: [Function],
show: [Function] }
当然您可以对此进行扩展,但关键思想是您 return 的对象需要包含您要调用的函数。 this
和原型是 JS 中比较容易混淆的部分之一。一个非常方便的简短文本是:Kyle Simpson 的“You Don't Know JS: this & Object Prototypes”。
感谢 Edwin 和 MarkM 的回复。我的主要问题是上下文。我需要 learnQuery(element).someMethod() 在与另一个方法链接时保留其上下文。我仍然无法完全理解 JS 中的 'this' ,以及如何确保它引用调用对象——尤其是当对象在闭包中调用函数 cutoff 时,就像我的示例中那样。我上面的例子使用了 learnQueryContext 变量来指出我知道这是我的问题所在,但我不知道如何保留上下文(即正确的对象)以便调用的函数对其进行操作并且 return想要的值。我非常接近。我没有像最初那样 return 编辑长对象,而是将它变成一个我可以在其内部引用的变量,然后 return 编辑该变量。这允许它保留正确的上下文。见下文:
function learnQuery(elementSelector) {
'use strict';
function cssPropProxy(property, value) {
return cssProp(elementSelector, property, value);
}
function ajaxReqProxy(url, options) {
return ajaxReq(url, options);
}
var cssClass = new CssClass();
var dom = new Dom();
var eventListener = new EventListener();
var returnedContext = {
cssProp : cssPropProxy,
ajaxReq : ajaxReqProxy,
cssClass: {
add: function(setClass) {
cssClass.add(elementSelector, setClass);
return returnedContext;
},
remove: function(deleteClass) {
cssClass.remove(elementSelector, deleteClass);
return returnedContext;
},
toggle: function(toggleClass) {
cssClass.toggle(elementSelector, toggleClass);
return returnedContext;
},
has: function(hasClass) {
return cssClass.has(elementSelector, hasClass);
}
}
};
return returnedContext;
}
现在我可以使用:
learnQuery('someElement').cssClass.add('someClass').cssClass.toggle('someClass');
并且它按预期工作。 cssClass 本身是我在别处定义的构造函数及其方法。这段代码只是一个接口,允许 learnQuery() 使用它们。
请告诉我您的想法以及您还可以如何解决它。
我正在尝试开发一个类似于 jQuery 的允许链接的库。我已经有了可用的函数,但我需要将它们链接在一起。请查看下面的代码并帮助我解决如何使用 'this' 访问正确的上下文并开发一个允许链接的类似于 jQuery 的库。我希望 'learnQuery()' 的功能类似于 jQuery()。我在将 cssClass 方法链接在一起时遇到问题。
function learnQuery(elementSelector) {
'use strict';
var learnQueryContext = this;
function cssPropProxy(property, value) {
return cssProp(elementSelector, property, value);
}
function ajaxReqProxy(url, options) {
return ajaxReq(url, options);
}
var cssClass = new CssClass();
return {
cssProp : cssPropProxy,
ajaxReq : ajaxReqProxy,
cssClass: {
add: function(setClass) {
cssClass.add(elementSelector, setClass);
return learnQueryContext;
},
remove: function(deleteClass) {
cssClass.remove(elementSelector, deleteClass);
return learnQueryContext;
},
toggle: function(toggleClass) {
cssClass.toggle(elementSelector, toggleClass);
return learnQueryContext;
},
has: function(hasClass) {
cssClass.has(elementSelector, hasClass);
return learnQueryContext;
}
}
是的,在尝试学习相同的东西之前,我正在玩类似的东西。我还有这个保存所以看看你是否能理解这个:
var $ = (function(){
$ = function(selector){ return new MyQuery(selector); };
var MyQuery = function(selector){
var nodes = document.querySelectorAll(selector);
this.each = Array.prototype.forEach.bind(nodes);
this.map = Array.prototype.map.bind(nodes);
var len = this.length = nodes.length;
for(var i = 0; i < len; i++) this[i] = nodes[i];
};
$.fn = MyQuery.prototype = {
addClass: function(classes){
this.each(function(el){
classes.forEach(function(className){
el.classList.add(className);
});
});
return this;
},
removeClass: function(classes){
this.each(function(el){
classes.forEach(function(className){
el.classList.remove(className);
});
});
return this;
},
addAttribute: function(newAttrib, value){
this.each(function(el){
el.setAttribute(newAttrib, value);
});
return this;
},
removeAttribute: function(attrib, value){
this.each(function(el){
el.removeAttribute(attrib);
});
return this;
},
remove: function(){
this.each(function(el){
el.remove();
});
return this;
},
on: function(type, callback){
this.each(function(el){
el.addEventListener(type, callback);
});
return this;
},
append: function(elem){
this.each(function(el){
el.appendChild(elem);
});
return this;
},
css: function(prop, value){
this.each(function(el){
el.style[prop] = value;
});
return this;
}
}
return $;
})();
很难弄清楚您希望使用这些函数发生什么。
cssPropProxy()
returns cssProp
但 cssProp
看起来只是对 cssPropProxy()
的引用。
链接的基本思想是 return 返回对象实例。在您的代码中,您似乎正在 return 引用该函数。这是一个可能有帮助的简单链接示例:
function chainingExample(startText){
return {
mytext: startText,
append: function(text){
this.mytext += text;
return this;
},
show: function(){
return this.mytext;
}
}
}
console.log(chainingExample("hello").append(" there").append(" again").show());
/* results in: "hello there again" */
以这种方式使用时 this
指向回 returned 对象。它看起来像:
{ mytext: 'hello there again',
append: [Function],
show: [Function] }
当然您可以对此进行扩展,但关键思想是您 return 的对象需要包含您要调用的函数。 this
和原型是 JS 中比较容易混淆的部分之一。一个非常方便的简短文本是:Kyle Simpson 的“You Don't Know JS: this & Object Prototypes”。
感谢 Edwin 和 MarkM 的回复。我的主要问题是上下文。我需要 learnQuery(element).someMethod() 在与另一个方法链接时保留其上下文。我仍然无法完全理解 JS 中的 'this' ,以及如何确保它引用调用对象——尤其是当对象在闭包中调用函数 cutoff 时,就像我的示例中那样。我上面的例子使用了 learnQueryContext 变量来指出我知道这是我的问题所在,但我不知道如何保留上下文(即正确的对象)以便调用的函数对其进行操作并且 return想要的值。我非常接近。我没有像最初那样 return 编辑长对象,而是将它变成一个我可以在其内部引用的变量,然后 return 编辑该变量。这允许它保留正确的上下文。见下文:
function learnQuery(elementSelector) {
'use strict';
function cssPropProxy(property, value) {
return cssProp(elementSelector, property, value);
}
function ajaxReqProxy(url, options) {
return ajaxReq(url, options);
}
var cssClass = new CssClass();
var dom = new Dom();
var eventListener = new EventListener();
var returnedContext = {
cssProp : cssPropProxy,
ajaxReq : ajaxReqProxy,
cssClass: {
add: function(setClass) {
cssClass.add(elementSelector, setClass);
return returnedContext;
},
remove: function(deleteClass) {
cssClass.remove(elementSelector, deleteClass);
return returnedContext;
},
toggle: function(toggleClass) {
cssClass.toggle(elementSelector, toggleClass);
return returnedContext;
},
has: function(hasClass) {
return cssClass.has(elementSelector, hasClass);
}
}
};
return returnedContext;
}
现在我可以使用:
learnQuery('someElement').cssClass.add('someClass').cssClass.toggle('someClass');
并且它按预期工作。 cssClass 本身是我在别处定义的构造函数及其方法。这段代码只是一个接口,允许 learnQuery() 使用它们。
请告诉我您的想法以及您还可以如何解决它。