суббота, 27 сентября 2014 г.

Методы, this

При создании объекта можно задать его методы:

var itchy = {
     color: "black",
     tail: true,
     voice: function { console.log("Meow!"); }
}

Методы можно вызывать двумя способами:

itchy.voice();  // > Meow!
itchy["voice"]; // > Meow!

Метод может создаваться и позже при помощи присваивания (обратить внимание на синтаксис):

var itchy = {
     color: "black",
     tail: true
}

itchy.voice = function() { console.log("Meow!"); };
itchy.voice();    // Meow!
itchy['voice'](); // Meow!

При необходимости обращаться к свойствам и методам объекта, нужно вызывать их по имени объекта и метода:

var itchy.whatColor = function() { console.log(color); }; 
// > SyntaxError.

var itchy.whatColor = function() { console.log(itchy.color); };
itchy.whatColor(); // > black

Но при удалении оригинальной переменной возникнет ошибка:

var scratchy = itchy;
itchy = null;
scratchy.whatColor(); // > TypeError

Для предотвращения таких ошибок нужно использовать this.
Ключевое слово this, использованное в методе объекта, ссылается на текущий объект. Можно обращаться к свойствам и методам объекта изнутри:

var itchy.whatColor = function { console.log(itchy.color); };
var scratchy = itchy;
itchy = null;
srcatchy.whatColor(); // > black

Некоторые объекты позволяют вызывать свои методы цепочкой:

maze.up().up().left().down().right();

Для этого каждый метод должен возвращать this:

maze = {
    up: function() { console.log("up!"); return this; },
    down: function() { console.log("down!"); return this; },
    left: function() { console.log("left!"); return this; },
    right: function() { console.log("right!"); return this; },
}

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

Текущий объект не является фиксированным и зависит от контекста вызова функции. Он может передаваться в функцию различными способами.

1. Неявно через вызов метода object.method(...);         //this = object
2. Неявно через вызов new   new constructor(...); //this = новый объект
3. Явно через call         function.call(object, ...); //this = object
4. Явно через apply        function.apply(object, ...);//this = object

Если ни один из этих способов не использован, то this указывает на Global Object для браузера - window для Node.js - global.

В случае 1 один и тот же метод-функция может быть присвоен разным объектам.

var itchy = { color : "black" };
var scratchy = { color : "white" };

var c = function() { console.log(this.color); };

itchy.whatColor = c;
scratchy.whatColor = c;

При вызове метода whatColor this для каждого объекта будет свой.

itchy.whatColor();
scratchy.whatColor();


В случае 2 конструктор может быть вызван и как обычная функция (без new). При этом this в обычном режиме будет ссылаться на глобальный объект (window, global), а в strict mode будет равен undefined.


Функции call и apply являются стандартными методами объекта типа function. Они позволяют (разово) выполнить произвольные функции в контексте объекта, указанного в качестве первого аргумента методов call и apply. Функция будет выполнена как метод объекта, даже если у объекта уже есть метод с таким именем. Назначения функции постоянным методом объекта как в случае с присваиванием не происходит.

var obj = { 
    prop: "value", 
    method: function() { console.log ("Do something!"); } 
};

var method = function() { console.log("Do something else!") };

obj.method();     // Do something!
method.call(obj); // Do something else!
obj.method();     // Do something!


Разница между call() и apply() заключается в обработке аргументов. Первым аргументом для обоих методов является объект, в контексте которого должны быть исполнена функция для которых вызывается метод. Далее call() принимает последовательность аргументов, а apply() - массив из аргументов.

func.call(context, arg1, arg2, ..., argN);
func.apply(context, [arg1, arg2, ..., argN);


Если первый аргумент call/apply равен null или undefined, то функция выполнится в контексте глобального объекта (с this равным window или global) в обычном режиме и с this равным null или undefined в strict mode.

При помощи apply можно сделать универсальную переадресацию вызова:

function f(a, b) {
    g.apply(this, arguments);
}

Функция g вызывается в том же контексте, что и f и с теми же аргументами. Код будет таким же для любого количества аргументов f.

Комментариев нет :

Отправить комментарий