Ответ 1
Метод call
устанавливает значение this
вызываемой функции для объекта, переданного как первый аргумент, в вашем примере выполняется метод Object.prototype.toString
объекта Array.
Объекты массива имеют свой собственный метод toString
(Array.prototype.toString
), который затеняет значение из Object.prototype
, если вы вызываете [].toString();
, будет вызван метод в Array.prototype
.
Например:
function test() {
alert(this);
}
test.call("Hello"); // alerts "Hello"
Другой пример:
var alice = {
firstName: 'Alice',
lastName: 'Foo',
getName: function () {
return this.firstName + ' ' + this.lastName;
}
};
var bob = {
firstName: 'Bob',
lastName: 'Bar',
};
alice.getName.call(bob); // "Bob Bar"
В приведенном выше примере мы используем метод Alice getName
для объекта Bob, значение this
указывает на bob
, поэтому метод работает так же, как если бы он был определен для второго объекта.
Теперь поговорим о методе Object.prototype.toString
. Все собственные объекты в JavaScript содержат внутреннее свойство, называемое [[Class]]
. Это свойство содержит строковое значение, которое представляет определенную спецификацией классификацию объекта, возможные значения для собственных объектов:
-
"Object"
-
"Array"
-
"Function"
-
"Date"
-
"RegExp"
-
"String"
-
"Number"
-
"Boolean"
-
"Error"
для объектов ошибок, таких как экземплярыReferenceError
,TypeError
,SyntaxError
,Error
и т.д. -
"Math"
для глобального объектаMath
-
"JSON"
для глобального объекта JSON, определенного в ECMAScript 5th Ed. спецификации. -
"Arguments"
для объектаarguments
(также введенного в спецификации ES5). -
"null"
(введено всего пару дней назад в ошибках ES5) -
"undefined"
Как я уже говорил, это свойство является внутренним, нет возможности изменить его, спецификация не предоставляет никакого оператора или встроенной функции для этого, и единственный способ получить доступ к его значению - через Object.prototype.toString
.
Этот метод возвращает строку, образованную:
"[object " + this.[[Class]] + "]"
Только для пояснительных целей, так как [[Class]]
не может быть доступен напрямую.
Например:
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(/foo/); // "[object RegExp]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call(new Date); // "[object Date]"
// etc...
Это действительно полезно для безопасного определения типа объекта, для обнаружения объектов массива, наиболее широко используемого метода:
function isArray(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
}
Может возникнуть соблазн использовать оператор instanceof
, но это приведет к проблемам, если вы работаете в средах с несколькими кадрами, потому что объект массива, созданный на одном кадре, не будет instanceof
Array
конструктор другого.
Вышеуказанный метод будет работать без каких-либо проблем, поскольку объект будет содержать значение его внутреннего свойства [[Class]]
.
См. также: