Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Улучшить код (https://javascript.ru/forum/dom-window/52022-uluchshit-kod.html)

OlegALL 30.11.2014 22:36

Улучшить код
 
Привет. Код: http://jsfiddle.net/nz2c2cva/1/

надо переписать строку проверки условия,
комментарий специалиста:
"В конструкторе проверять this, если this не твой инстанс,
то вызывать заново конструктор внутри себя уже с new",
причём это решение должно быть лучше

if (this.$) {
	return new $(selector);
}


Написал так: if (this instanceof window.constructor) , но специалист не принял, сказав, что ничего не улучшилось

Так же, скажите, почему такой вариант лучше

Vlasenko Fedor 30.11.2014 22:50

if (!(this instanceof $)) {
    return new $(selector);
}

зачем учиться так, чтоб за тебя решали?

krutoy 30.11.2014 23:49

не уверен, что правильно понял, но, похоже, ты хотел вот так сделать
<html>
<head>
<meta charset="windows-1251" />
</head>
<body>
 
<div class="class0"> <a href="">link</a> </div>
<div class="class0"></div>
<div class="class0"></div>
<script>

var $ = function (selector){
        var o=Object.create($.prototype)
	o.tags = document.querySelectorAll(selector);
        return o
}

$.prototype.addClass = function(className){
	for (var i = 0; i < this.tags.length; i++){
		this.tags[i].classList.add(className);
	}
	return this;
}

$.prototype.copyHtml = function(){
       var html=this.tags[0].innerHTML
       for(var i = 1; i < this.tags.length; i++){
           this.tags[i].innerHTML=html
       }
}

$('div').addClass('class2').copyHtml();


</script>
</body>
</html>

krutoy 01.12.2014 00:00

И вот так,
var $ = function (selector){
			
			this.tags = document.querySelectorAll(selector);

никогда не делай.
Если уж используешь эту клоунаду, сначала рекурсивный вызов через new, а уже потом присваивание. Например,
$=function(selector){
   if (!(this instanceof $)) return new $(selector);
   this.tags = document.querySelectorAll(selector);
   ...

а в твоем случае, this===window, соответственно, ты туда срешь.

krutoy 01.12.2014 00:18

А вообще, эту хрень проще безо всякого prototype написать, он тут ни к чему, по-моему
<html>
<head>
<meta charset="windows-1251" />
</head>
<body>
 
<div class="class0"> <a href="">link</a> </div>
<div class="class0"></div>
<div class="class0"></div>
<script>




var $ = function (selector){
        var o=Object.create($)
	o.tags = document.querySelectorAll(selector);
        return o
}

$.addClass = function(className){
	for (var i = 0; i < this.tags.length; i++){
		this.tags[i].classList.add(className);
	}
	return this;
}

$.copyHtml = function(){
       var html=this.tags[0].innerHTML
       for(var i = 1; i < this.tags.length; i++){
           this.tags[i].innerHTML=html
       }
}

$('div').addClass('class2').copyHtml();


</script>
</body>
</html>

но все зависит от юзкейса, конечно.

OlegALL 01.12.2014 07:08

Цитата:

Сообщение от Poznakomlus (Сообщение 343669)
if (!(this instanceof $)) {
    return new $(selector);
}

зачем учиться так, чтоб за тебя решали?

Я абсолютно не знаю как это делать, поэтому и спрашиваю

Спасибо, а почему так лучше?

OlegALL 01.12.2014 07:10

Цитата:

Сообщение от krutoy (Сообщение 343675)
А вообще, эту хрень проще безо всякого prototype написать, он тут ни к чему, по-моему
<html>
<head>
<meta charset="windows-1251" />
</head>
<body>
 
<div class="class0"> <a href="">link</a> </div>
<div class="class0"></div>
<div class="class0"></div>
<script>




var $ = function (selector){
        var o=Object.create($)
	o.tags = document.querySelectorAll(selector);
        return o
}

$.addClass = function(className){
	for (var i = 0; i < this.tags.length; i++){
		this.tags[i].classList.add(className);
	}
	return this;
}

$.copyHtml = function(){
       var html=this.tags[0].innerHTML
       for(var i = 1; i < this.tags.length; i++){
           this.tags[i].innerHTML=html
       }
}

$('div').addClass('class2').copyHtml();


</script>
</body>
</html>

но все зависит от юзкейса, конечно.


Код не надо изменять, это задание, которое почти выполнено

danik.js 01.12.2014 07:35

Цитата:

Сообщение от OlegALL
Я абсолютно не знаю как это делать, поэтому и спрашиваю

Ды должен был спросить не как это сделать, а почему твой вариант неправильный. А перед этим разобраться и пояснить нам что такое конструктор, и как работает оператор new. Если бы разобрался, то понял сам чего от тебя хотят и реализовал бы.

OlegALL 01.12.2014 09:02

Я понимаю, что такое конструктор и new.

Тем не менее, объясните, почему проверка
if (!(this instanceof $))
лучше, чем
if (this.$)


Кроме того,
даже используя отладчик не пойму как работает этот код:
$.prototype.html = function(){
	                var clone = new $('_');
			clone.tags = this.tags;
			clone.toString = function() {
				console.log("|");
				return this.tags[0].innerHTML;
			};
			console.log("||");
			return clone;
}


Точнее - в каком порядке исполняются инструкции return.
Как я понял сначала отрабатывает return clone, затем функция toString()?
Отладчик не заходит в toString

nerv_ 01.12.2014 10:35

Цитата:

Сообщение от OlegALL
но специалист не принял

безобразие :D

Цитата:

Сообщение от OlegALL
Я понимаю, что такое конструктор и new

если бы понимал, не писал бы такой ерунды

а еще не понятно, зачем такое извращение
$.prototype.html = function(){
    var clone = new $('_');
    clone.tags = this.tags;
    clone.toString = function() {
        return this.tags[0].innerHTML;
    };
    return clone;
}

если достаточно
// getter
$.prototype.html = function(){
    return this.tags[0].innerHTML;
}

http://api.jquery.com/html/
http://code.jquery.com/jquery-2.1.1.js

OlegALL 01.12.2014 10:45

Цитата:

Сообщение от nerv_ (Сообщение 343707)
безобразие :D


если бы понимал, не писал бы такой ерунды

а еще не понятно, зачем такое извращение
$.prototype.html = function(){
    var clone = new $('_');
    clone.tags = this.tags;
    clone.toString = function() {
        return this.tags[0].innerHTML;
    };
    return clone;
}

если достаточно
// getter
$.prototype.html = function(){
    return this.tags[0].innerHTML;
}

http://api.jquery.com/html/
http://code.jquery.com/jquery-2.1.1.js

потому что условие сделать так:
$('div').html().addClass('class2').html()

Я прошу ответить точно на мои вопросы либо дать напутствия, остальные вопросы решены

danik.js 01.12.2014 15:52

Цитата:

Сообщение от nerv_
а еще не понятно, зачем такое извращение

Это мой код )

Ему нужно было чтобы html() не прерывал цепочку вызовов (только не понимаю какой тогда смысл в его вызове ). Про toString ему подсказал его "специалист".

Написал наскоряк. По идее надо создавать класс, наследующийся от $, с перекрытым toString. Причем в каждом вызове любого метода должен возвращаться новый инстанс, чтоб не тянулся один по цепочке.

danik.js 01.12.2014 15:53

Цитата:

Сообщение от OlegALL
потому что условие сделать так:
$('div').html().addClass('class2').html()

А нахуя вызывать html() , не используя результат? Твой спец - ебанат. Так ему и передай.

nerv_ 01.12.2014 15:58

Цитата:

Сообщение от danik.js
Ему нужно было чтобы html() не прерывал цепочку вызовов

я про это :)

OlegALL 01.12.2014 16:04

почему
if (!(this instanceof $))

лучше, чем
if (this.$)

?

Мне больше ничего не надо

nerv_ 01.12.2014 16:11

OlegALL, потому, что конструктор может быть вызван без new. А твоя проверка вообще не понятно что делает :)

danik.js 01.12.2014 16:50

Цитата:

Сообщение от OlegALL
почему лучше, чем

Первая проверка проверяет, что конструктор вызван без слова new, и тогда форсируется вызов через new, дабы создать все-таки объект.

Вторая проверяет что конструктор вызван в контексте объекта, у которого есть свойство $. Ну типа предполагается что был вызов Constructor(), и контекст тогда window, и проверяется window.$.


Стоит сделать Constructor.call({$:1}) и твоя глюкавая проверка не сработает :D

OlegALL 01.12.2014 22:34

Спасибо. но я так и не понял, чем же второй вариант лучше. Какая разница, как проверять вызов конструктора?
Constructor.call({$:1})
- это вообще непонятно, к чему
т.е.
if (this.$)
- это ненадёжно? когда-то сработает, а когда-то нет?

danik.js 01.12.2014 22:47

Цитата:

Сообщение от OlegALL
Какая разница, как проверять вызов конструктора?

:blink:

danik.js 01.12.2014 22:49

Цитата:

Сообщение от OlegALL
это вообще непонятно, к чему

$.call({$:1})

OlegALL 01.12.2014 23:03

$.call({$:1})
- в смысле если $ примет значение 1, то не сработает?

danik.js 01.12.2014 23:21

Запусти да посмотри.

OlegALL 02.12.2014 00:18

но ведь
this.$
вызывает $ без явного указания this, причём тут это
$.call({$:1})
?

danik.js 02.12.2014 06:00

Немного ошибся. Тестируем твою проверку вот так:

function $(selector) {
	if (this.$) {
		alert('Вызван не как конструктор');
		//return new $(selector);
	} else {
		alert('Вызван как конструктор');
	}
}
$('x'); // ок
$.call({}, 'x'); // фэйл



(function(window, document) {
	function $(selector) {
		if (this.$) {
			alert('Вызван не как конструктор');
			return new $(selector);
		} else {
			alert('Вызван как конструктор');
		}
	}
	$('x'); // фэйл
})(window, document);


Чет уж слишком легко ее наебать.

OlegALL 02.12.2014 09:15

ты хотел подчеркнуть, что this.$ зависит от внешнего окружения?
можешь объяснить, почему
(function(window, document) {
		function $(selector) {
                     if (this.$){}   // this.$ = undefined ???, хотя this = Window
                }
}



function $(selector) {
     if (this.$){}   // this.$ = тело функции $; this = Window
}


и что это за функция-обёртка?
(function(window, document) {
})(window, document);
- извини, что надоел с вопросами, уже нет времени исследовать

ruslan_mart 02.12.2014 10:54

if(this === window) {
   return new $(....);
}

OlegALL 02.12.2014 11:02

if(this === window)

и что? в обоих случаях
this === window
это true

ruslan_mart 02.12.2014 11:15

OlegALL, нет.

var $ = function(selector) {
    alert(this === window);
    if(this === window) return new $(selector);
}
      
$('bla');

OlegALL 02.12.2014 11:45

уже совсем ничего не понимаю

скажите, вот это
(function(window, document) {
})(window, document);
- создаётся для задания области видимости (замыкания)?

danik.js 02.12.2014 14:29

Ruslan_xDD, а если this - не window будет, то конструктор так и не будет вызван? Тоже проверка корявая. Че выдумывать то, а? Все уже придумано до нас.

ruslan_mart 02.12.2014 15:03

danik.js, ну если он же и делает сам это всё для какого-то сайта, на кой ему нужно будет вызывать $ через call/apply?

В принципе, достаточно сделать:

if('$' in this) return new $(.....);

OlegALL 02.12.2014 15:07

Это учебное задание, которое специально составлено на прокачку скиллов

danik.js 02.12.2014 15:09

Цитата:

Сообщение от Ruslan_xDD
danik.js, ну если он же и делает сам это всё для какого-то сайта, на кой ему нужно будет вызывать $ через call/apply?

И че, значит надо делать через жопу?

ruslan_mart 02.12.2014 15:16

danik.js, нет. Я не считаю, что '$' in this или this.$ - это через задницу. В jQuery вроде как раз так и написано.

Вот у тебя когда-нибудь была необходимость вызывать jQuery через call? Зачем её вообще через call кому-то понадобится вызывать?

krutoy 02.12.2014 15:28

Цитата:

Сообщение от Ruslan_xDD
что '$' in this или this.$ - это через задницу

Это именно через задницу. Зачем вообще вызывать ф-цию дважды только для того, чтобы создать объект? Это все равно, что писать var a = a = 1, это тупость по-любому. Про call/applay правильно сказали, а не используют, просто потому что четкого понимания работы этих ф-ций ни у кого нет. Вызовешь в контексте экземпляра, и перезапишешь свойства, и вообще, хз что может быть.

danik.js 02.12.2014 15:34

Цитата:

Сообщение от Ruslan_xDD
В jQuery вроде как раз так и написано.

Фигня. Смотрим: https://github.com/jquery/jquery/blo...rc/core.js#L23

var
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init( selector, context );
};

danik.js 02.12.2014 15:35

Цитата:

Сообщение от krutoy
Зачем вообще вызывать ф-цию дважды только для того, чтобы создать объект?

Расскажи это разработчикам jQuery, а то они не в курсе.

krutoy 02.12.2014 15:36

Цитата:

Сообщение от danik.js
Расскажи это разработчикам jQuery, а то они не в курсе.

А мне плевать на разработчиков, хоть жеквери, хоть х*я, я просто констатирую факт.

Erolast 02.12.2014 15:40

Правильно делаешь, ты ведь умнее разработчиков jQuery.

krutoy 02.12.2014 15:43

Цитата:

Сообщение от danik.js
return new jQuery.fn.init( selector, context );

Это, кстати, говнокод, по большому счету. Есть конвенция, употреблять оператор new только для создания экземпляра класса, а ф-ция, должна быть с большой буквы. Грязный хак мартышки, которая не знает как_сделать_это_правильно


Часовой пояс GMT +3, время: 10:58.