Что означает «это» в JavaScript? - PullRequest
4 голосов
/ 17 декабря 2010

Я не уверен, куда это указывает в JavaScript.И я привожу 2 примера.

Можете ли вы помочь мне проанализировать их?Большое спасибо.

//exmp1
function f1()
{
  alert(this);
  function f2()
  {
    alert(this);
  }
  f2();
}
f1();

//exmp2
var jsn = 
{
  name : "b",
  func : function() // closure
  {
    alert(this); 
    return function()
    {
      return this;
    }
  }
}

alert(jsn.func()());

Ответы [ 4 ]

13 голосов
/ 17 декабря 2010

this отличается в JavaScript от других языков, таких как C ++ или Java.Значение this в вашем первом примере всегда будет глобальным объектом (window в браузерах).this во втором примере - это объект jsn для первого предупреждения и window для второго.Это потому, что this определяется полностью тем, как вызывается функция, а не тем, где она определена.

Если вы не делаете ничего особенного при вызове функции, thisглобальный объект.Когда вы вызываете функцию через свойство объекта (jsn.func()), this устанавливается для объекта, из которого получено свойство.(Но не поймите неверное впечатление, func никоим образом не привязан к jsn; JavaScript не имеет методов , только функции; детали .) f1 затем возвращает функцию, которая вызывается в финале alert;поскольку этот вызов не осуществляется через свойство объекта, для глобального объекта устанавливается this.

Некоторые примеры:

// Simple function
function foo() {
    alert(this === window);
}
foo(); // true, within the call, `this` === `window`

// Object example, and twist at the end
var obj = {
    func: function() {
        alert(this === obj);
    },
};
obj.func();    // true, within the call, `this` === `obj`
obj["func"](); // true, within the call, `this` === `obj`

var f = obj.func; // Not calling it, just getting a reference to the function
f(); // false, within the call `this` !== `obj` (`this` === `window`)

// Creating functions on the fly, returning them, and how that has
// nothing whatsoever to do with how `this` gets set:
var obj = {
    func: function() {
        return function() {
            alert("I'm a generated function");
            alert(this === obj);
        };
     }
};
obj.func()(); // alerts the "I'm a generated function", then false; `this` !== `obj`
obj.bar = obj.func();
obj.bar();    // alerts the "I'm a generated function", then true; `this` === `obj`

Существует второй способ управления тем, что находится внутри thisфункция: используйте функции JavaScript .call или .apply:

var obj = {
    func: function() {
        alert(this === obj);
    }
};
function foo(a, b) {
    alert(this === obj); // Yes, really obj; see below
    alert(a);
    alert(b);
}
foo(1, 2);               // alerts false (`this` !== `obj`), then 1, then 2
obj.func();              // alerts true, `this` === `obj`
foo.call(obj, 3, 4);     // alerts true (`this` === `obj`), then 3, then 4
foo.apply(obj, [5, 6]);  // alerts true (`this` === `obj`), then 5, then 6

Как видите, первый аргумент call или apply - это объект, который нужно сделать thisв вызове функции.Единственная разница между call и apply заключается в том, как вы указываете аргументы для передачи в целевую функцию: при call вы просто предоставляете их после первого аргумента;с помощью apply вы предоставляете их в виде массива.

И, наконец, есть третий способ: ключевое слово new.JavaScript имеет концепцию функций конструктора .Назначение функции конструктора - создавать экземпляры объектов, инициализированных определенным образом.Вот пример:

function Foo(b) {
    this.bar = b;
}
var f = new Foo();

Технически, любая функция может использоваться в качестве функции конструктора.Соглашение состоит в том, чтобы предоставлять функции, предназначенные для использования с new именами, начинающимися с заглавной буквы, просто для подтверждения того, что мы вызываем их особым образом.

Вызов функции через new создает новый объектэкземпляр и делает этот объект значением this в вызове функции.Итак,

function Foo(b) {
    alert(this === window);
}
var f = new Foo(); // alerts false, `this` !== `window` (it points to the new object created for the call)
var f = Foo();     // alerts true, `this` === `window` because we didn't use `new`

Как видите, важно правильно вызывать функцию.Если он предназначен для использования с new, позвоните по номеру new;если это не так, не надо.

(new делает больше, чем просто создает пустой объект; у созданного объекта есть некоторые другие аспекты, настроенные определенным образом. Я не буду вдаваться в подробности здесь, но я не хотел оставлять у вас впечатление, что все это было создание нового экземпляра объекта.)

1 голос
/ 17 декабря 2010

В JavaScript «this» всегда относится к объекту, которому «принадлежит» функция, или, точнее, к объекту, к которому функция была привязана через свойство во время ее вызова.Рассмотрим этот пример:

var f = function() { alert(this); }
f(); // Alerts the "DOM window" (global) object, which
     // is implied if there is no explicit owner.
var o = {toString:function(){return "Foo!";}}
o.func = f;
o.func(); // Alerts the "Foo!" object (o) since the
          // function then belongs to it as a member.

Теперь, что касается ваших конкретных примеров, вот что происходит:

//exmp1
function f1() {
  alert(this);
  function f2() {
    alert(this);
  }
  f2(); // Alerts "the global object", since f2
        // is not bound to any object's property.
}
f1(); // Alerts "the global object" (probably DOM window)
      // for same reason as above.

//exmp2
var jsn = {
  name : "b",
  func : function() {
    alert(this); // Will alert the "jsn" object, since it
                 // owns the function in its "func" member.
    return function() {
      return this; // Returns whoever is calling it!
    };
  }
}
alert(jsn.func()()); // "jsn.func()" returns a function which gets
                     // called by the global "DOM window" object.
1 голос
/ 17 декабря 2010

В вашем последнем примере (функция внутри объекта json), this относится к объекту json, который содержит функцию.

В вашем первом примере первый this ссылается на объектто есть f1, это глобальный оконный объект.Вторая this в f2 также относится к глобальному объекту, а не к f1, и это известная ошибка в javascript , когда одна функция определена в другой.

Обычный обходной путь - это (не каламбур):

function f1() {
  alert (this);
  var that = this;
  function f2() {
    alert (that);
  }
  f2();
}

Обратите внимание, что если вы определите функцию в объекте json, ее все равно можно будет "перемещать", и контекст this изменится,Например:

var car1 = {
  color: "red",
  f: function () { alert (this.color); }
}

car1.f(); // prints "red"

var car2 = {
  color: "blue",
}

car2.f = car1.f;

car2.f(); // prints "blue"
0 голосов
/ 17 декабря 2010

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

function Test() {
  this.test = true;
}

t = new Test();
alert(t.test);
...