Цепочка вызовов jQuery
Привет
Задача - сделать так: $('div').addClass('class1').html().addClass('class 2').html(); (без new), не создавая экземпляра класса, оставив при этом прототипное наследование.
function $(selector){
this.tags = document.querySelectorAll(selector);
}
$.prototype.addClass = function(className){
for (var i = 0; i < this.tags.length; i++){
this.tags[i].classList.add(className);
}
return this;
}
$.prototype.html = function(){
this.tags[0].innerHTML;
console.log(this.tags[0].innerHTML);
return this;
}
new $('div').addClass('class1').html().addClass('class2').html();
|
|
Цитата:
OlegALL, ты, что вообще хочешь получить? Присвоить ДИВу два класса и вернуть его ХТМЛ? |
Цитата:
|
Цитата:
var val=$('div').addClass('class1 class2').html();
|
Спасибо Erolast за ссылку. Получилось так:
var $ = function (selector){
this.tags = document.querySelectorAll(selector);
if(this.$) {
return new $(selector);
}
}
$.prototype.addClass = function(className){
for (var i = 0; i < this.tags.length; i++){
this.tags[i].classList.add(className);
}
return this;
}
$.prototype.html = function(){
this.tags[0].innerHTML;
console.log(this.tags[0].innerHTML);
return this;
}
$('div').addClass('class1').html().addClass('class2').html();
Только вопрос: почему зацикливается вызов $, если писать так: return new $(selector); а не так:
if(this.$) {
return new $(selector);
}
|
Цитата:
<html>
<head>
</head>
<body>
<div>foo</div>
<div>bar</div>
<div>baz</div>
<script>
var $ = function (selector){
this.tags = document.querySelectorAll(selector);
if(this.$) {
return new $(selector);
}
}
$("div")
alert(tags)
</script>
</body>
</html>
|
Цитата:
Логика такая: если this - инстанс конструктора $, то все пучком, делаем поиск по селектору. Если же нет - создаем инстанс сами через new и возвращаем результат. Таким образом, когда будешь писать $('div'), то будет два вызова - один как вызов функции, второй - как вызов конструктора (через new, создание инстанса то есть). Оно у тебя и щас так работает, но условие не совсем подходящее. |
Цитата:
|
danik.js,
Слушай, по-моему это чушь какая-то. Какие нах*й инстансы и классы? цель банальна -- вернуть (псевдо) объект, так? Так почему бы не написать тупо
proto={}
$=function(sel){
var o = document.querySelectorAll(sel)
o.__proto__=proto
return o
}
proto.addClass = function(className){
for (var i = 0; i < this.length; i++){
this[i].setAttribute("class", className)
}
return this;
}
и так далее. Зачем этот цирк? |
danik.js,
можно даже так, чтоб лишние имена в глобале не плодить:
<html>
<head>
<style>
.foo{background: red}
</style>
</head>
<body>
<div>foo</div>
<div>bar</div>
<div>baz</div>
<script>
$=function(sel){
var o = document.querySelectorAll(sel)
o.__proto__=$
return o
}
$.addClass = function(className){
for (var i = 0; i < this.length; i++){
this[i].setAttribute("class", className)
}
return this;
}
$("div").addClass("foo")
</script>
</body>
</html>
|
спасибо, вариант krutoy - наиболее удачный
|
Цитата:
Цитата:
|
OlegALL,
Прошу прощения, чуть поспешил. В ФФ не работает, может еще где. Вот этот код протестировал в ФФ Хроме и старой опере. В IE не тестил.
<html>
<head>
<style>
.foo{background: red}
</style>
</head>
<body>
<div>foo</div>
<div>bar</div>
<div>baz</div>
<script>
$=function(sel){
var extend=function(src, trg){
for(var i in src) if(!isNaN(i)) trg[i]=src[i]
}
var o = Object.create($)
extend(document.querySelectorAll(sel), o)
console.log(o)
return o
}
$.addClass = function(className){
for(var i in this){
if(this[i].setAttribute) this[i].setAttribute("class", className)
}
return this;
}
$("div").addClass("foo")
</script>
</body>
</html>
Но гарантировать нгичего не могу, сам экспериментирую:) Это все из-за идиотского поведения нативного API, этих гребаных коллекций, которые и объекты, сука, и не объекты. |
Цитата:
Цитата:
Интересно было бы на твою версию взглянуть. Или опять сольешься? |
Цитата:
Цитата:
Так на ES6:
class $ {
constructor(selector) {
if (!(this instanceof $))
return new $(selector);
Object.assign(this, document.querySelectorAll(selector));
}
addClass(className) {
for (let element of Array.from(this)) {
element.classList.add(className);
}
return this;
}
}
Так на ES5:
function $(selector) {
if (!(this instanceof $))
return new $(selector);
var queryResult = document.querySelectorAll(selector);
for (var i = 0; i < queryResult.length; i++) {
this[i] = queryResult[i];
}
this.length = queryResult.length;
}
$.prototype.addClass = function(className) {
for (var i = 0; i < this.length; i++) {
var element = this[i];
if (~element.className.indexOf(className))
continue;
else
element.className += (" " + className);
}
return this;
}
|
Цитата:
Цитата:
Цитата:
Цитата:
Расскажи, чипушила, чем твоя $ отличается от этой
function $(selector) {
var o=Object.create($.prototype),
queryResult = document.querySelectorAll(selector);
for (var i = 0; i < queryResult.length; i++) {
o[i] = queryResult[i];
}
o.length = queryResult.length; return o
}
посмеши пацанов. Ты делаешь финты ушами только для того чтобы создать объект? Lol. |
Цитата:
Цитата:
|
Erolast, на конец предыдущей строки посмотри.
|
Сейчас другой вопрос.
<body> <div class="class0"> <a href="">link</a> </div> <div class="class0"></div> <div class="class0"></div> </body>
proto={};
$ = function(selector){
var tags = document.querySelectorAll(selector);
tags.__proto__ = proto;
return tags;
}
proto.addClass = function(className){
for (var i = 0; i < this.length; i++){
this[i].classList.add(className);
}
return this;
}
proto.html = function(){
return this[0].innerHTML;
}
console.log( $('div').addClass('class1').html() ); так работает console.log( $('div').addClass('class1').html().addClass('class 2').html() ); а так нет. html() с одной стороны должен возвращать this[0].innerHTML, а с другой this. Как это объединить не знаю. На несовершенство кода пока обращать внимания не надо. как-то надо использовать toString() / valueOf() |
Цитата:
Энивей, он в глобале var не использует, что привносит неочевидности - создается впечатление, что эта переменная уже была где-то объявленна (не говоря уже о том, что не во всех имплементациях внешний код в выполняется в глобале). Цитата:
|
Цитата:
|
Erolast,
И, кстати, насчет твоего предыдущего высера по поводу явного/неявного. Если я изнутри функции меняю глобальную переменную, которая еще не объявлена, это не значит, идиот, что это делается неявно. На самом деле, я меняю перемнную со значением undefined на переменную со значением some_value, семантически. Неявно -- это когда ты не понимаешь, что ты делаешь, примерно как ты. Если ты по тупости своей, непреднамеренно изменил переменную в глобале, или создал, вот это есть неявно. В остальных случаях -- все явно, идиот.
local={}
;(function(){this.x=1}).apply(window)
;(function(){this.x=1}).apply(local)
alert([window.x, local.x])
Задумайся, ущерб, почему бы тебе не объявлять в local переменные через вар, lol. Это тебе, блять, не паскаль, здесь семантика massage passing. Вот из=-за таких уродов как ты, отрыжек дейксры, нормальный язык изуродовали до неузнаваемости. |
Продолжаем решение поиска ответа:
Нужно, чтобы цепочка не разрывалась Код:
var $ = function (selector){
this.tags = document.querySelectorAll(selector);
if (this.$) {
return new $(selector);
}
}
$.prototype.addClass = function(className){
for (var i = 0; i < this.tags.length; i++){
this.tags[i].classList.add(className);
}
return this;
}
$.prototype.html = function(){
return this.tags[0].innerHTML;
}
console.log($('div').addClass('class1').html().addClass('class2')); // нужно, чтобы работало
комментарий от специалиста, который поставил задачу: "Надо переопределить toString у this внутри методов. Теперь если результат ты используешь как строку, она у тебя и будет строкой, хотя возвращать ты будешь this" Попробовал, не работает. И вообще, не знаю как это сделать. Даже не совсем понял комментарий. Помогите |
Да с чего ты вообще взял, что это должно работать? html возвращает данные, он прерывает текучий интерфейс и ставится последним в цепочке вызовов. Какова, по-твоему, его функция при расположении в середине? Красоты ради?
|
Ну тогда надо не this возвращать, а новый объект. Иначе такой код не будет работать:
var $div = $('div');
var html = $div.html(); // меняет toString на выдачу html
var text = $div.text(); // меняет toString на выдачу text
alert(html); // выдаст text вместо html
Но тогда html !== $div, но по-другому и быть не может, иначе возникает противоречие. |
Да это просто не нужно. html в любом случае будет в конце цепочки распологаться, иначе он не вернет данные == не нужен.
|
Кстати, html возвращает клон, и он тащится далее по цепочке. Таким образом $().html().addClass().toString() вернет html, а не [object Object]
Значит, нужно в каждом методе создавать клон. Короче, херня получается.
<div>This is <b>content</b></div>
<script>
var $ = function (selector){
this.tags = document.querySelectorAll(selector);
if (this.$) {
return new $(selector);
}
}
$.prototype.addClass = function(className){
for (var i = 0; i < this.tags.length; i++){
this.tags[i].classList.add(className);
}
return this;
}
$.prototype.html = function(){
var clone = new $('_');
clone.tags = this.tags;
clone.toString = function() {
return this.tags[0].innerHTML;
};
return clone;
}
var $div = $('div').addClass('class1').html().addClass('class2');
console.log($div); // нужно, чтобы работало
alert($div.html());
</script>
|
Спасибо!
Сейчас 3 вопроса: 1. так: alert($('div').addClass('class1').html().addClass( 'class2').html()); - всё гуд а так: console.log($('div').addClass('class1').html().add Class('class2').html()); - выводит this ($ {tags: NodeList[3], toString: function, addClass: function, html: function}) почему? 2. Объясните смысл
if (this.$) {
return new $(selector);
}
Здесь нужно переделать. Комментарий специалиста: "if (this.$) - плохое решение. Лучше проверять instanceof." Мне пока непонятно 3. почему в клоне нет проверки
if (this.$) {
return new $(selector);
}
И можно ли сделать наследование от $? или фактически оно и есть? UPD. Текущий код:
var $ = function (selector){
this.tags = document.querySelectorAll(selector);
if (this instanceof window.constructor) {
return new $(selector);
}
}
$.prototype.addClass = function(className){
for (var i = 0; i < this.tags.length; i++){
this.tags[i].classList.add(className);
}
return this;
}
$.prototype.html = function(){
var clone = new $('_');
clone.tags = this.tags;
clone.toString = function() {
return this.tags[0].innerHTML;
};
return clone;
}
Правильно ли сделано это:
if (this instanceof window.constructor)
{
return new $(selector);
}
|
| Часовой пояс GMT +3, время: 16:37. |