|
Ключевое слово this в javascript работает своеобразно, не так, как в других языках.
В отличие от PHP, Java, C++ и т.п, значение this в javascript не привязывается статически ни к какому объекту, а зависит от контекста вызова.
Разберем все 4 возможных случая.
Если функция вызывается через new как конструктор объекта, то this ставится на создаваемый объект:
function Animal(name) {
this.name = name
}

В результате получается объект, инициализированный конструктором, с заполненным свойством name.
Если функция запущена как свойство объекта, то в this будет ссылка на этот объект.
obj.func(параметры)
// или
obj['func'](параметры)
При этом совершенно неважно, откуда эта функция взялась. Важно лишь, какой перед func стоит объект.
Создадим два любых объекта:
vasya = {
name: "Василий"
}
dima = {
name: "Дмитрий"
}
Определим никак не связанную с ними функцию say:
say = function() {
alert("Привет, я "+this.name)
}
Присвоим функцию свойству sayHi для обоих объектов:
vasya.sayHi = say
dima.sayHi = say
И теперь тестовый запуск:
vasya.sayHi() // => "Привет, я Василий"
dima.sayHi() // => "Привет, я Дмитрий"
// или так
dima['sayHi']()
В обоих случаях запускается одна и та же функция say, которая получает в this объект до точки.
Функцию можно вызвать, используя методы call и apply.
func.apply(obj, [параметры])
func.call(obj, параметр)
При таком вызове this будет установлен в obj.
Оба метода работают одинаково, но для call аргументы подставляются в вызов, а для apply - передается массив.
function sum(a,b) {
this.c = a + b
}
var obj = {}
sum.call(obj, 1,2)
// или
sum.apply(obj, [1,2])
alert(obj.c) // => 3
Вызов через apply удобен тем, что можно самостоятельно сформировать массив аргументов или модифицировать существующий.
say()
При таком вызове this ставится равным глобальному объекту (в браузере это window). Обычно, если функция использует this, то она не подразумевает запуск в таком виде, так что в 90% случаев такое значение this - результат ошибки в программе, глюк.
Если кратко срезюмировать все вышесказанное, то получится такая вот шпаргалка:

|
Автор: freelancer (не зарегистрирован), дата: 19 июня, 2008 - 17:54
#permalink[a href="#" onclick="myFunction(this)"]
при таком вызове this будет указывать на [a] я так понимаю
Автор: Octane (не зарегистрирован), дата: 9 июля, 2008 - 11:04
#permalinkДопустим у нас есть такой набор функций
function addEvent(obj, type, listener) { if(obj.addEventListener) { obj.addEventListener(type, listener, false); } else if(obj.attachEvent) { obj.attachEvent('on' + type, listener); } } function $(id) { var obj = document.getElementById(id); obj.bind = function(type, listener) { addEvent(this, type, listener); return this; } return obj; }тогда как сделать чтобы внутри вызова
$('id').bind('click', function() { alert(this); });this указывало на объект полученный через $('id')?
Автор: Octane (не зарегистрирован), дата: 9 июля, 2008 - 23:21
#permalinkСпасибо.
Собственно проблема была только в ИЕ, изменил код следующим образом:
obj.attachEvent('on' + type, function() {listener.apply(obj);});только теперь непонятно как реализовать detachEvent, может существует какойто другой способ?
Автор: polymorphm (не зарегистрирован), дата: 14 января, 2009 - 07:39
#permalinkдумаю без ещё одного проверочного тэста -- не доконца всё ясно.
вот этого :
var a = new Object(); a.who = "I am A!"; a.b = new Object(); a.b.who = "I am A->B!!"; a.b.c = new Object(); a.b.c.who = "I am A->B->C!!!"; a.b.c.func = function () { window.alert(this.who); } // главный тэст a.b.c.func(); // что выдаст -- "I am A!" или "I am A->B->C!!!" ??? // вспомогательный тест (навсякий случай) a.b.func = a.b.c.func; a.b.func(); // this не "приклеелся"-ли ?ато может показаться непонятно как себя поведёт this в случае с ЦЕПОЧКОЙ объектов ..
в результате приведёного примера -- появляется "I am A->B->C!!!" и затем "I am A->B!!" (но небыло ниразу "I am A!" , а также заметим что this не приклеивался к телу "функции" . а подставлялся динамически) ...
.. это значит что в приведёном случае -- this работает также как this и в C++ , PHP и определённых других языках.....
Автор: m4d_5h4d0w (не зарегистрирован), дата: 15 января, 2009 - 23:05
#permalinkЗдравствуйте.
Подскажите плиз, как избавиться от переполнения стэка... Я головой понимаю, что что-то глупое делаю, но найти второй день не могу.
Аналог кода:
function _obj () { this.int1 = 0; this.time = 0; this.a = function () { <...some code...> this.b(); } this.b = function () { if (this.int1 != 1) { this.time++; setTimeout('this.b();', 100); // Вот эта гадость приводит к "стэк оверфлоу". } else { alert(time); } } } var obj = new _obj;Чтобы вопросов лишних не было - int1 изменяется пользователем вне функции, функция считает время. Я понимаю, что там чего-то с кавычками делать, но: а) без кавычек, ессесно, недопустимый аргумент, б) с ними оверфлоу, в) единственное, как оно работает - это прописать setTimeout('obj.b();' 100);<...> т.е. ссылка напрямую на еще не созданный объект. Но это есть уродство
, тем более хотелось бы универсальный объект. Выносить функцию вне объекта тоже не очень хочется.
Заранее спасибо)
Автор: m4d_5h4d0w (не зарегистрирован), дата: 15 января, 2009 - 23:27
#permalinkПрошу прощения, уже нашел, здесь же, на сайте, так что все равно еще раз спасибо)) (сделал через
вар селф = зис;
сетТаймаут(функция () {селф.б()}, 100)
)
Автор: Rust (не зарегистрирован), дата: 27 февраля, 2009 - 01:26
#permalinkесть ява функция
function head_fahren1() { var Xq = this.offsetLeft var Y = this.offsetTop document.getElementById("login").value=""+Xq+"-"+Y }к ней обращщается объект TABLE:
Но this все равно определяется,как window. Почему?
Автор: kefi, дата: 23 марта, 2009 - 19:46
#permalink[quote]При таком вызове this ставится равным глобальному объекту window.[/quote]
Есть тут, imho, две ошибки, причем первая по всей статье прослеживается.
1) Конечно хорошо быть лаконичным, но имеющуюся ввиду фразу "присваивает this указатель на ... " лучше не произносить как "this ставится на ...", что может у многих новичков (у меня в т.ч.) вызвать неверное понимание с точностью до наоборот (русский язык это позволяет) , как содержимое this кладется в ... Лучше лаконично говорить "this указывает на ..." или вот в случае выше "ставит на него this" - "направляет на него this"
2) this в этом случае уазывает на глобальный объект, но глобальный объект в разных реализациях ECMA script, который в народе называют Javascript не есть window, это тоже затеняет смысл, который заключается в следующем :
Первоначально у глобального объекта срели прочих могут быть свойства, значением которых является сам глобальный объект
Так в наиболее распространенных браузерных javascript - глобальный объект имеет одно из свойств window, которое указывает на глобальный объект. В JScript реализации ECMAScript'а в WSH, например нет вообще свойства window, там глобальный объект имеет среди прочих пару полезных свойств WScript и WSH, но это не глобальный объект. В ActiveScript реализации ECMA script - не знаю, есть ли свойство window и свойство , указывающее на глобальный объект.
PS. просто сейчас пытаюсь разобраться в некоторых связанных с this и контекстами вопросах, не всегда удается ...
Автор: Бегимот (не зарегистрирован), дата: 25 марта, 2009 - 11:06
#permalinkРеспект автору, достойная инфа по теме.
Автор: spike (не зарегистрирован), дата: 8 августа, 2009 - 17:34
#permalinkСпасибо за труд!
По-моему, этот код из примера надо исправить:
say = function(phrase) { alert("Привет, я "+this.name) }Параметр phrase лишний. Так же?
Ерунда, но для читабельности полезным будет.
Автор: Dariraze (не зарегистрирован), дата: 1 сентября, 2009 - 09:52
#permalinkПодскажите, пожалуйста, не могу понять, как мне получить в функции ссылку на объект?
function imgCrop() { this.obj = document.getElementById("obj"); this.obj.addEventListener("mousemove", this.func, true); } imgCrop.prototype.func() { alert(this); // this ссылается на сам элемент this.obj, как мне получить сам объект ImgCrop? }Автор: Pellegrino, дата: 22 февраля, 2010 - 12:35
#permalinkПодскажите пожалуйста, почему не работает такой код:
function closer(){
this.showsec= 15;
}
closer.prototype= {
progress: function(){
alert(this);
},
start: function(){
alert(this);
setTimeout.call(this, this.progress, 1000 );
}
}
var cl= new closer();
cl.showsec= 20;
cl.start();
Автор: Pellegrino, дата: 22 февраля, 2010 - 12:51
#permalinkПочитал статью про замыкания, переписал так:
start: function(){ var that= this; function progress(){ lg(that); }; alert(this); setTimeout( progress, 1000); }но вреравно интересно, почему не работает
Автор: Pellegrino, дата: 22 февраля, 2010 - 14:46
#permalinkхотя такой вариант работает
function k(){ alert(this.bb); } function k2(){ this.bb= 15; setTimeout.call(this, k, 1000 ); } k2();Автор: DenSparrow (не зарегистрирован), дата: 16 июня, 2010 - 11:55
#permalinkЗдравствуйте!
А, если можно, объясните, пожалуйста, в чём разница между конструкцией из примера про "Васю и Диму":
say = function(){ alert("Hi, I am " + this.name); }и конструкцией:
say = function(){ alert("Hi, I am " + arguments.callee.name); }Или это два идентичных способа сделать одно и тоже действие, просто первый - короче?
Автор: crefezentee (не зарегистрирован), дата: 5 февраля, 2011 - 03:08
#permalinkхорошее начало
Автор: Monte (не зарегистрирован), дата: 12 марта, 2011 - 10:39
#permalinkvar viewBaner = { img:null, ShowBaner : function(a) { alert(a); // почему то выдает не [object] а значение его href // почему не передается весь объект? //this.img.src='1.gif'; }, Replace : function() { this.img = document.getElementById('img'); var a = document.getElementsByTagName('a'); var _this = this; a[0].onmouseover= function(){ _this.ShowBaner(this)}; } } viewBaner.Replace();подскажите пожалуйста как в этих случаях работает this
Автор: kiborg (не зарегистрирован), дата: 20 марта, 2011 - 23:00
#permalinkизвините пожалуйста, подскажите код, удаляющий строку, например в таблице на которую нажали?
Автор: Гость (не зарегистрирован), дата: 1 апреля, 2011 - 14:48
#permalinkесли использовать jquery
то проще некуда
$("#table td").click(function(){ $(this).remove(); });Автор: Гость (не зарегистрирован), дата: 1 апреля, 2011 - 14:50
#permalinkа вот так удалится что угодно
$("*").click(function(){ $(this).remove(); });Автор: Гость (не зарегистрирован), дата: 14 июня, 2011 - 19:02
#permalinkПомогите пожалуйста разобраться
function obj1(){ this.div=document.createElement("div"); document.body.appendChild(this.div); this.txt=document.createTextNode("test"); this.div.appendChild(this.txt); this.showalert= function () { alert(this.txt.nodeValue); } this.div.onclick=this.showalert; } var a=new obj1();результат -ошибка this.txt is udefined
Автор: Гость (не зарегистрирован), дата: 16 августа, 2011 - 12:15
#permalinksay = function() {
alert("Привет, я "+this.name)
}
vasya = {
name: "Василий"
}
dima = {
name: "Дмитрий"
}
vasya.sayHi = say
dima.sayHi = say
не работает, подскажите плз где у меня ошибка
Автор: pashak, дата: 24 августа, 2011 - 20:52
#permalinkРаботаю с JavaScript уже более трёх лет. Хотелось бы поделиться опытом по этой теме. Может, это уже известно вам, но не отнеситесь критически, потому что это полезно для новичков.
Уменьшаем расход памяти
Я заметил, что есть тенденция использовать замыкания, там, где без них можно и обойтись. На самом деле замыкания - это очень плохо при неправильном использовании. Всё дело в памяти. Несмотря на концепцию, что скриптовый программист (наш любимый JS, например) чаще всего не должен задумываться об используемой памяти (все автоматизировано и происходит без его участия), стОит думать, сколько выделено на ту или иную вкладку памяти, потому что механизм замыканий может скушать a lot of memory. Для оптимизации использована именно особенность слова this.
Возьмём всё тот же пример из темы замыканий, где каждому [div] (в моём случае - [a] и их в 100 раз больше) присваивается вызов alert() с номером в цикле. Тестировал я в хроме, потому что там удобное отображение расхода памяти для каждой из вкладок.
Первый пример:
(function init(){
for(var i=1000,a;i--;){
a=document.body.appendChild(document.createElement("a"));
a.href="#";
a.innerHTML="сообщение: "+i+";";
a.onclick=(function init(x){
return function onclick(){
alert(x);
return false;
};
})(i);
}
})();
На оптимизацию в виде обратного прохода не обращайте внимания - это не ключевой момент.
В этот примере использован механизм замыканий. Т.е. для каждого элемента браузер создаёт НОВУЮ функцию с ЗАМЫКАНИЕМ (если быть точнее, то с обращением к замкнутой переменной) внутри неё. Хром показал расход памяти в 23,2 МБ для данной вкладки.
Вариант 2:
(function init(){
for(var i=1000,a;i--;){
a=document.body.appendChild(document.createElement("a"));
a.href="#";
a.innerHTML="сообщение: "+i+";";
a.$data=i;
a.onclick=function onclick(){
alert(this.$data);
return false;
};
}
})();
Механизм замыканий исключён, память больше не расходуется на так называемую [[closure scope]]. Использована возможность присваивать элементам (как и любым объектам) пользовательские свойства (я назвал его $data, но это дело уже лично каждого). Согласно спецификации внутри функции onclick this показывает на элемент, на котором произошло событие, с которого [элемента], собственно, и берём данные. Хром показывает 20,5 МБ. Для меня - это существенный выигрыш (а что, если объектов несколько миллионов?). Но функций, как и в предыдущем примере создаётся тоже 1k.
Третий пример:
(function init(){
var f=function onclick(){
alert(this.$data);
return false;
};
for(var i=1000,a;i--;){
a=document.body.appendChild(document.createElement("a"));
a.href="#";
a.innerHTML="сообщение: "+i+";";
a.$data=i;
a.onclick=f;
}
})();
На моё мнение оптимизировано максимально, т.е. улучшать уже некуда: одна функция для тысячи элементов, она использует механизм this. Хром показывает 20,0 МБ. Всего-то 500k, но оптимизация тоже проихошла. Напомню, что в пользовательские свойства можно вписывать любые значения: числа, строки, объекты.
Настоятельно рекомендую пользоваться именно таким механизмом в подобных случаях. Как пример - реализация модели MVC.
P.S. Извиняюсь за поехавшие в коде табы.
Автор: Wayne, дата: 18 сентября, 2011 - 18:29
#permalink>> "P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью."
- Джон Рейсиг "Профессиональные приёмы программирования на JavaScript".
Как говорится, прочитал всё от корки до корки. Касательно только JavaScript на этом сайте.
Замечательный сайт в плане общего ознакомления с тем, что такое JavaScript. И всё же скажу, что об ООП здесь сказано на очень низком уровне. Статьи про объекты и ООП здесь читателям позволят научиться лишь не блуждать в коде, который они читают. Сами они навряд ли смогут после прочтения этих статей что-либо сделать.
И всё же сайт на столько же хорош в своей тематики, на сколько в своей htmlbook.ru.
Для тех же, кто желает продолжить изучение и научиться хорошо(профессионально) программировать на JavaScript, хотел бы посоветовать книгу Джона Рейсига(главного разработчика библиотеки jquery) под названием "Профессиональные приёмы программирования". Хорошая книга, которая позволит вникнуть в суть JavaScript, познакомит с технологией Ajax и, что немаловажно, научит мыслить в режиме ООП.
В данной книге напрочь отсутствуют введение в JavaScript и прочие обучающие детали. Поэтому эта книга очень хороша для того, чтобы продолжить изучать JavaScript сразу после прочтения статей на этом сайте. =)
P.S. отсутствие введения и прочей шелухи для новичков сократило объём книги с стандартных 700-1000 страниц для книг схожей тематики, до 250.
Автор: bykastar, дата: 3 октября, 2011 - 15:28
#permalinkПрошу прощения, всё работает! Комент удалить бы.
Автор: Гость (не зарегистрирован), дата: 10 апреля, 2012 - 20:01
#permalinkПодскажите пожалуйста в моём случае
function a(){ this.b = 'Hello'; $('#id').click(function(){ alert(this.b); }) }Как мне обойти эту ситуацию и обратиться к свойству b ..... можно конечно перед этим поставить var self = this и обращаться уже к self, а есть ли более изящный способ ?
Автор: natalitvinenko, дата: 31 мая, 2012 - 14:31
Как бы на клиентской стороне выяснить в скрипте путь до самого этого скрипта-ну то, что на серверной стороне выглядит как WScript.ScriptFullName ? Сунулась сюда в надежде, что this и есть оно, так нет :-)
Автор: clearwater (не зарегистрирован), дата: 19 июня, 2012 - 18:57
#permalinkИмеем:
function test(){ alert(this); }В IE8 - [object.Window]
В FF 3.6.8 - [object.Window]
В FF 13 (Linux64) - undefined
В Chromium (Linux64) 19.0.1084.56 - undefined
Вопрос: и как это понимать?
Автор: Actine, дата: 28 июня, 2012 - 16:24
#permalinkМожно еще дописать, на всякий случай, что в такой-вот конструкции:
this будет obj2, и, как я понял, это единственная ситуация, где следует вызывать функцию через call/apply, а не напрямую.
(объясняю, если нужно вызвать функцию, которая находится в каком-то объекте, но как this передать ей не этот объект, а другой. В принципе, нужный объект можно и параметром передать, но иногда такой вариант удобнее, в особенности если у Вас смоделированы "абстрактные классы", как тот же Math)
Автор: Grkov (не зарегистрирован), дата: 15 июля, 2012 - 18:46
#permalinkВсем привет...
var a = { 'name' : 'a', 'say' : function () { console.log(this.a) } 'b' : { 'name' : 'b' } }Как заставить работать a.b.say() ?
т.е требуется сохранить вложенность b в а, b должен тянуть уже определенную функцию say в "родителе"
Как вариант
var a = { 'name' : 'a', 'say' : function () { console.log(this.a) } 'b' : { '__proto__' : a, 'name' : 'b' } }Но это зацикливание ссылок, браузер не ругается.. но это не гуд...
Автор: Гость (не зарегистрирован), дата: 15 июля, 2012 - 18:47
#permalinkВсем привет...
var a = { 'name' : 'a', 'say' : function () { console.log(this.name) } 'b' : { 'name' : 'b' } }Как заставить работать a.b.say() ?
т.е требуется сохранить вложенность b в а, b должен тянуть уже определенную функцию say в "родителе"
Как вариант
var a = { 'name' : 'a', 'say' : function () { console.log(this.name) } 'b' : { '__proto__' : a, 'name' : 'b' } }Но это зацикливание ссылок, браузер не ругается.. но это не гуд...
Автор: Гость (не зарегистрирован), дата: 11 октября, 2012 - 15:01
#permalinkСвойства, методы события объектов доступные в коде для элементов, где нибудь водятся здесь ?... Или все попутались в атрибутах HTML тегов, DOM...
Автор: Гость (не зарегистрирован), дата: 23 ноября, 2012 - 08:57
#permalinkfunction Pic (N,T,d,f,w,h,r) { this.Name=N; this.Tip=T; this.razmehnadiske=d; this.razmerfaila=f; this.width=w; this.height=h; this.razreh=r; this.izmen=function() {document.write ('<img src="this.Name.this.Tip" this.width="" this.height="">');} } var Pic1=new Pic("pict1","jpg","F:\ukigrad",100,300,600,1024); var Pic2=new Pic("pict2","jpg","F:\ukigrad",300,900,1200,2024);как правильно описать картинку с помощью объектов которые есть?
Автор: Гость (не зарегистрирован), дата: 25 августа, 2013 - 06:21
#permalinkВопрос к гуру js.
Имеется код (это всего лишь удобный пример, но суть вопроса остается)
// основной объект Country = { name: 'Russia', capital: { name: 'Moscow', showDescription: showCapitalDescr } } // другой объект, просто чтобы понять, почему showCapitalDescr вынесена в отдельную ф-цию AntiCountry = { name: 'USA', capital: { name: 'Washington', showDescription: showCapitalDescr } } // собственно ф-ция function showCapitalDescr() { alert(this.name + ' is the capital of ' + this.[[parent_obj]].name); // тут надо обратиться к полю name "родительского" объекта }Нужно обратиться к свойству Country.name изнутри объекта capital. Есть ли какие более-менее элегантные способы это сделать? Кроме переделывания всего кода с созданием двух классов Country, Capital, и специального поля country внутри Capital (для хранения к какой стране принадлежит) и с последующим присваиванием в виде
Так код становится намного больше, появляется перекрестная ссылка, а главное - для моей задачи классы вовсе не нужны, по сути только 2 "статичных" объекта, а то и 1.
Похожий вопрос уже задавался в комментарии чуть выше, но ответа не было. Тут либо возможности js особо не позволят развернуться, чтоб так сделать, либо найдется спец, который решит данную задачку.
Автор: Гость (не зарегистрирован), дата: 5 сентября, 2013 - 13:03
#permalinkОчевидно, на этом сайте не тусят специалисты в js)) Одни кодеры, что и умеющие так только добавить в html событие onclick)
Автор: hfts (не зарегистрирован), дата: 26 января, 2014 - 19:41
#permalinkПомогите разобраться, вообщем есть такой код:
$(document).ready(function(){
function Boxs(width,height,bgColor){
this.width = width;
this.height = height;
this.bgColor = bgColor;
}
var box = new Boxs(250,250,'green');
var box2 = new Boxs(200,200,'yellow');
//Создание коробки
Boxs.prototype.createBox = function(width,height,bgColor){
$('#idDiv').append('
');
$('.clBox').css({'width' : this.width+'px', 'height' : this.height+'px', 'background-color' : this.bgColor, 'margin' : '80px'});
}
box.createBox();
box2.createBox();
});
Когда я вызываю метод "createBox()" оно создает блок с заданными параметрами в объекте "box", но если я после этого вызову тот же метод но уже для другого объекта который имеет другие параметры, то "this" будет брать параметры из "box2", и сделает 2 блока со свойствам "box2".
Как сделать так что бы у меня вышли 2 блока с разными параметрами (только осваиваю js).
Просьба помочь.