2012-04-16 2 views
1

Я новичок в Javascript, и я только что открыл ключевое слово property для определения функций для объектов. Я попытался реорганизовать мой эксперимент с использованием объектов, но я не могу заставить его работать.Как назначить функции в javascript?

Это не работает (нет объектов):

var ws = new WebSocket(something, somethingelse); 
ws.onopen = function() { 
    ws.send("hello"); 
    console.log("works"); 
} 

Но это не делает:

function MyObject() { 
    this.ws = new WebSocket(something, somethingelse); 
    this.ws.onopen = this.onOpen; 
} 

MyObject.prototype.onOpen = function() { 
    this.ws.send("hello"); // undefined! 
}; 

Почему WS не определено? Я неправильно назначил функцию onOpen?

+2

Вы используете ключевое слово 'new'? Здесь есть куча вещей; Что именно ты пытаешься сделать? –

+1

Какое «ключевое слово свойства»? –

+0

Функция onOpen будет вызываться объектом WebSocket, а «this» будет фактически объектом WebSocket, но не MyObject. (* Если я не возился с вещами arround .. *) – moka

ответ

6

Вы правильно назначаете функции (есть только один способ назначения функций), ваша проблема в том, что контекст функции изменяется.

Рассмотрим следующую строку:

this.ws.onopen = this.onOpen; 

Возможность 1:

Теперь я полагаю, внутриWebSocket, где эта функция вызывается, как ответ на соединение открытия (например, обработчик событий), вероятно, как

this.onopen(); 

What this refers to inside a function is determined by how a function is called on run time (<- прочитайте эту ссылку, это очень помогает). Он не связан во время определения. В вашем случае this ссылается на экземпляр WebSocket.

Так внутри, если назвать этот путь, внутри MyObject.prototype.onOpen, this относится к this.ws, то WebSocket экземпляр, который не имеет ws свойство, а не MyObject экземпляр.

Это может быть решена двумя способами:

  1. С this уже относится к this.ws, вы можете позвонить send непосредственно на this:

    MyObject.prototype.onOpen = function() { 
        this.send("hello"); 
    }; 
    
  2. Если вы хотите this внутри MyObject.prototype.onOpen всегда обратитесь к экземпляру MyObject, вы должны содержать явную ссылку на экземпляр, например через закрытие:

    var self = this; 
    this.ws.onopen = function() { 
        self.onOpen(); 
    }; 
    

    Теперь внутри onOpen, this относится к MyObject экземпляра, который имеет свойство ws, так же, как вы установите его в конструкторе.

    В браузерах, поддерживающих ECMAScript 5, функции уже есть метод для этого метода, называемого .bind():

    this.ws.onopen = this.onOpen.bind(this); 
    

Возможность 2:

Это также может быть, что WebSocket звонки onopen таким образом:

this.onopen.call(null); 

В этом случае this будет либо обратиться к window или будет undefined, в зависимости от того, работает ли код в строгом режиме или нет (это не имеет значения, в любом случае это проблема).

Эта ситуация может быть решена только с помощью второго решения первой возможности.


Почему первый пример работает?

var ws = new WebSocket(something, somethingelse); 
ws.onopen = function() { 
    ws.send("hello"); 
    console.log("works"); 
} 

В этом случае функция присваиваемое ws.onopen является закрытие, закрытие по переменным, определенным в этой области, а также ws. В этом смысле он аналогичен второму способу решения проблемы, но

ws.onopen = function() { 
    this.send("hello"); 
    console.log("works"); 
} 

, вероятно, будет работать.

+0

Да, я сделал что-то похожее на это, когда я работал с WebSockets. –

+0

Ах, одна из самых непонятых функций JavaScript. Это ключевое слово. –

+0

Спасибо за отличное объяснение! – wannabeartist

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