2012-03-15 3 views
4

Примера коде:JavaScript вопросы о ключевых словах этого

<!DOCTYPE html> 
<html> 
<head> 
    <title>test</title> 

    <script language="javascript" type="text/javascript"> 

    function init() { 
     var nodeList = document.getElementsByTagName("a"); 
     var nodeArr = []; 
     for(var i = 0; i < nodeList.length; i++) // Copy NodeList to Array 
      nodeArr.push(nodeList[i]); 
     for(var i = 0; i < nodeArr.length; i++) // Loop over array 
      if(nodeArr[i].className == "clickLink") 
       nodeArr[i].onclick = clickLink2; // Attach event function 
    } 

    window.onload = init; //Attach event function 

    function clickLink2() { 
     console.log("this: " + this); //Prints window URL in href 
     console.dir(this); //show attributes of anchor  
     console.log(this.name); // Prints name attribute 
    } 


    function clickLink(elem) { 
     console.log("this: " + this); //Prints [object Window] 
     console.dir(this); // Shows attributes, etc. al of [object Window] 
     console.log("name: " + elem.name);  
    } 
    </script> 

    </head> 

    <body> 

    <!-- inline --> 
    <a href="#" name="blah1" onclick="clickLink(this); return false;">Test 1</a> 
    <a href="#" name="blah2" onclick="clickLink(this); return false;">Test 2</a> 
    <a href="#" name="blah3" onclick="clickLink(this); return false;">Test 3</a> 
    <a href="#" name="blah4" onclick="clickLink(this); return false;">Test 4</a> 


    <hr/> 
    <!-- not inline --> 
    <a href="#" name="blah5" class="clickLink">Test 5</a> 
    <a href="#?t" name="blah6" class="clickLink">Test 6</a> 
    <a href="#" name="blah7" class="clickLink">Test 7</a> 
    <a href="#" name="blah8" class="clickLink">Test 8</a> 

    </body> 

    </html> 

Я сделал тестирование в Firefox, с поджигателями для просмотра вывода консоли.

Теперь то, что мне было интересно:

  1. Почему в clickLink делает это относятся к объекту окна?
  2. Почему это в clickLink2 печатать на консоль как значение href ссылки?
  3. Есть ли лучший способ передать этот ненавязчивому приложению вроде этого? как вы можете быть уверены, что такое это?

ОК, так что я взял отрывки из ответов здесь и обнаружили, что это немного изворотливый в некоторых браузерах. Кроме того, назначение функции onclick отличается тем, что прикрепляется (но, к сожалению, не все версии IE поддерживают это либо см. addEventListener vs attachEvent). По какой-то причине более старые IE также делают , это внутри тела функции запуска события по-прежнему относятся к объекту окна, а не к вызывающему. Поэтому я использовал event.srcElement. Вот несколько новых примеров кода:

<!DOCTYPE html> 
<html> 
<head> 
    <title>test</title> 

<script language="javascript" type="text/javascript"> 

function init() { 
    var nodeList = document.getElementsByTagName("a"); 
    var nodeArr = []; 
    for(var i = 0; i < nodeList.length; i++) // Copy NodeList to Array 
     nodeArr.push(nodeList[i]); 
    for(var i = 0; i < nodeArr.length; i++) // Loop over array 
    if(nodeArr[i].className == "clickLink") { 

     var a = nodeArr[i]; 

     if (a.addEventListener) { //IE9, other browsers 
      a.addEventListener('click', clickLink2); // Attach event function 
     } else if (a.attachEvent) { //IE6,7,8, etc. 
      a.attachEvent('onclick', clickLink2); // Legacy IE Attach event function 
     }   

     a.onclick = function() { return false }; // override default onclick behavior for these anchors so URL is not followed 
    } 
} 

window.onload = init; //Attach event function 

function clickLink2() { 

    if(typeof(event) != 'undefined') { 
     elem = event.srcElement; //IE < 8 keeps this as window object 
    } else { 
     elem = this;  
    } 

    alert(elem.name); 
} 


function clickLink(elem) { 
    alert(elem.name); 
} 
</script> 

</head> 

<body> 

<!-- inline --> 
<a href="#" name="blah1" onclick="clickLink(this); return false;">Test 1</a> 
<a href="#" name="blah2" onclick="clickLink(this); return false;">Test 2</a> 
<a href="#" name="blah3" onclick="clickLink(this); return false;">Test 3</a> 
<a href="#" name="blah4" onclick="clickLink(this); return false;">Test 4</a> 


<hr/> 
<!-- not inline --> 
<a href="#" name="blah5" class="clickLink">Test 5</a> 
<a href="#?t" name="blah6" class="clickLink">Test 6</a> 
<a href="#" name="blah7" class="clickLink">Test 7</a> 
<a href="#" name="blah8" class="clickLink">Test 8</a> 

</body> 

</html> 
+4

Похоже, вам нужно прочитать о ['this'] (https://developer.mozilla.org/en/JavaScript/Reference/Operators/this) – zzzzBov

+1

Вы передаете ссылку на текущий элемент' onclick = " clickLink (this) 'и получая его в' function clickLink (elem) 'как' elem'. Почему бы не использовать его? – Stefan

+1

@Stefan Код, который я представляю, на самом деле не предназначен для каких-либо конкретных действий, просто чтобы попытаться выяснить что ключевое слово _this_ делало в разных ситуациях. В сочетании с ссылкой MDN от zzzzBov, объяснениями ниже и моим собственным мастером, я думаю, что теперь у меня есть лучшая ручка _this_ в Javascript. Спасибо всем – user17753

ответ

2

1) Почему в clickLink ли это относиться к объект окна? Проще говоря: clickLink не является обработчиком событий, добавив атрибут onclick к элементам, вы используете собственный метод onclick как обработчик, вызывающий функцию. эта функция объявляется в основной области, поэтому это указывает на объект окна. Чтобы было ясно: поведение похоже на это:

<p onclick='function(){window.clickLink(this);}'> 

Создание фактического обработчик события анонимную функцию, не clickLink. Вот почему это укажет на окно: анонимная функция тоже была объявлена ​​в глобальной области, поэтому вызывающий элемент clickLink - это окно.

2) Почему это в clickLink2 печатает на консоль как значение href ссылки?

Подумайте об этой фразе «Javascript позволяет вам манипулировать DOM, DOM-деревом, всеми событиями и поведением». В вашей функции init управляются элементы управления onclick. метод по умолчанию onclick отменяется и заменяется на clickLink2 здесь nodeArr[i].onclick = clickLink2;.

Посмотрите на это так: все ваши элементы имеют прототип метода onclick, который принимает параметр. В первом случае этот параметр представляет собой строку, которая оценивает вызов функции clickLink. Однако во втором случае экземпляры, имеющие определенный класс, имеют свой собственный метод onclick, перекрывающий прототип onclick.

Я надеюсь, что это немного облегчит вам жизнь. Это легко, как только вы поймете основную философию событий, обработчиков, методов, прототипов и т. Д. ... и преодолеете причуды JS.

3) Есть ли лучший способ передать это ненавязчивому приложению, как это? как вы можете быть уверены, что это значит?

Ну, вроде ответ, что выше, не так ли? но так или иначе: если вы сами определяете метод элемента или объекта, в общем случае это укажет на объект/элемент владельца. Если вы полагаетесь на html и поведение по умолчанию, JS будет в основном учитывать его собственный бизнес, и это укажет на окно.

Я не знаю, если это вариант, но, может быть, вы могли бы попробовать что-то вроде этого:

<a onclick='clickLink'> 

это должно -в theory- делать то же самое, что ваша функция инициализации

Edit: работает альтернатива выше:

<p onclick='clickLink.call(this)'> 

Вызов определяет элемент p как вызывающий элемент clickLink, делая эту точку элементом, который вызывает функцию.

2

Когда вызываются обработчики inline-событий, они запускаются в глобальном масштабе. Вот почему this является window.

Когда обработчики событий фактически привязаны к элементу, они вызываются в контексте этого элемента, как при запуске метода, который является частью объекта. Это делает элемент this.

Например:

function test(){ 
    console.log(this); 
} 
test(); // window 

var obj = { 
    test: test 
} 
obj.test(); // obj 

Чтобы быть уверенным, что this, вы должны приложить обработчик событий с помощью JS (с element.addEventListener или element.onClick), а не с помощью встроенных обработчиков.

+1

Право, в моем примере кода, который я изучил как встроенные, так и динамически связанные обработчики событий.Я пытался определить разницу между этими двумя методами.Это кажется, что если я присоединю функцию динамически через 'addEventLi stener', что _this_ внутри тела присоединенной функции будет ссылаться на вызывающего абонента, который поднял событие. – user17753

2

Это была одна из самых удивительных вещей, которые я узнал о JavaScript, исходя из фона .NET.

this, когда используется в методе, не относится к определенному объекту. Это относится к вызывающему абоненту или к объекту, который вызвал событие, которое привело к вызову обработчика события.

Чтобы ответить на номер 3 из ваших вопросов: просто скопировать то, что это относится к новой переменной:

var thisThis = this; 
//now pass thisThis. Interesting huh? 
//thisThis will not change with the change of the context. 
//this alone is a keyword that changes depending on 
//the context: e.g. who is the caller, what object raised the object, etc. 
+0

Что я пытался сказать с №3, было то, что inline вы можете передать _this_ без проблем в качестве первого аргумента, такого как 'elem' в' clickLink'. _this_ в inline 'a' относится к самому элементу и хранится в параметре' elem'. Принимая во внимание, что когда я присоединяю функцию динамически, например, через 'addEventListener', я не могу передать _this_ так, как я сделал встроенный. Я думаю, это не проблема, так как _this_ в теле присоединенной функции все равно ссылается на вызывающего. – user17753

+0

Кроме того, мне было интересно, с № 2: это только тот случай, когда тег 'a' при печати на консоль' toStrings' на значение его 'href'? – user17753

2

this переменная, указывающая на текущий объем.Если выполнить следующий код в консоли:

var myPackage = {} 
myPackage.method = function() {console.log(this)} 
myPackage.method() 

this будет указывать на myPackage объект (сфера применения method).

Вместо если вы пытаетесь запустить следующее:.

console.log(this) // window 

это (окно) является ссылкой на окно текущего браузера сценарий выполняется в

+0

«scope» имеет немного другое значение в JavaScript. Это может быть не лучшее слово, потому что оно неоднозначно. – pimvdb

Смежные вопросы