2011-11-30 12 views
7

odkryłem osobliwość w JavaScript (lub może pomysł mojego przeglądarki z IT):Dlaczego łańcuch zostaje okaleczony, gdy staje się "tym"?

var s = "Hello, world"; 

function foo(arg) 
{ 
    console.log(arg); 
    console.log(this); 
} 

foo.call(s, s); 

Running wyżej z Firebug konsoli włączona, otrzymuję:

Hello, world 
String { 0="H", 1="e", more...} 

Dlaczego ciąg automatycznie się zamienił do dziwnego obiektu, zanim zostanie this przekazany do foo?

Powodem, dla którego nazywam to dziwnym obiektem, jest dławik jQuery. Na przykład:

$.each(["one", "two", "three"], function(i, x) { 
    $('<p></p>').text(x) .appendTo('body'); // Works 
    $('<p></p>').text(this).appendTo('body'); // Doesn't work 
}); 
+0

Cóż, "to" powinno odnosić się do 'okna', jeśli nie jest ono wewnątrz funkcja. – mc10

+0

Interesujące zachowanie, zakładając, że przekazuje niepoprawną liczbę argumentów. Używam obiektu arguments, jeśli istnieje zmienna liczba argumentów. –

Odpowiedz

4

this jest zmuszany do obiektu, tj Object("test") jest wewnętrznie nazywa.

(function() { 
    return this; 
}).call("test"); 

// returns same as `new String("test")` or `Object("test")` 

if the method is a function in non-strict mode ... primitive values will be boxed*.

Zauważ, że w trybie ścisłej rzeczywiście ma zwrócić wartość prymitywną:

(function() { 
    "use strict"; 
    return this; 
}).call("test") === "test"; // true 

* Boxing a value of a value allocates an object instance and copies the value into the new object.

1

Ponieważ this jest tylko obiekt (wiem ciągi są obiektami, ale są również ciągi):

var s = "Hello, world"; 

function foo(arg) 
{ 
    console.log(typeof arg); // string 
    console.log(typeof this); // object 
} 

foo.call(s, s); 
1

Podczas korzystania foo.call(s1, s2), jesteś funkcja foo wywoływanie i ustawienie słowa kluczowego this do s1. Ponieważ this musi być obiektem (a więc nie prymitywną wartością), jest konwertowany na obiekt String.

poszczególne znaki z łańcucha (stworzonego przez s = "..." lub s = String("...")) można uzyskać za pośrednictwem indeksów, stąd

String { 0="H", 1="e", more...} 

function foo(arg) 
{ 
    console.log(arg); // passed as "Hello, world" 
    console.log(this); // passed as String("Hello, world") 
    console.log(this instanceof String); //True 
} 


kodu wykazać indeksy:

var i=0, s = "Hello, world"; 
for(; i<s.length; i++){ 
    console.log(i, s[i]); 
} 
/* Prints: 
    0 H 
    1 e 
    ... 
    */ 
*/ 
Powiązane problemy