Поведение, которое вы испытываете при использовании метода toString
, вызвано тем, что при выполнении конкатенации строк объект неявно преобразуется в строку (с помощью ToPrimitive
внутренняя операция с использованием подсказки типа "String").
Этот метод вызывает другую внутреннюю операцию, [[DefaultValue]](hint)
.
Если тип подсказки имеет тип String, эта операция явно получает свойство toString
и вызывает его.
Если ваш объект явно не определяет метод toString
, метод все равно будет разрешен выше в цепочке прототипов, "[object Object]"
является результатом метода Object.prototype.toString .
Например:
var obj = {
toString:function () {
return "hello";
}
};
alert(obj + ' world');
// will alert "hello world"
Теперь о значении this
:
Способ создания ваших объектов также известен как цепочка конструктора , значение this
будет ссылаться на новый объект, который наследует от прототипа конструктора, который вы вызвали с помощью оператора new
.
При вызове другого конструктора с call
просто будет сделано, чтобы все присваивания свойств, сделанные для значения this
внутри вызываемой функции, фактически выполнялись для нового объекта из первого конструктора, который на самом деле не влияет на прототип цепочки, например:
function Person(w,h){
this.width = w;
this.height = h;
}
function Man(w,h,s) {
Person.call(this, w, h); // will just apply the width and height assignments
this.sex = s;
}
var person = new Person(1,2);
person instanceof Person; // true
person instanceof Man; // false
var man = new Man(1,2,3);
person instanceof Person; // false
person instanceof Man; // true
Редактировать: Чтобы уточнить, когда вы вызываете Person.call(this, ...);
, он просто вызывает эту функцию, чтобы назначить свойства значению this
(this.width
и this.height
в вашем примере) для этой функции объекту, переданному в качестве первого аргумента call
, упрощенный пример:
function Test () {
this.foo = 1;
this.bar = 2;
this.baz = 3;
}
var obj = { foo: 0 }; // a simple object
Test.call(obj);
// now obj looks like this: {foo: 1, bar: 2,baz: 3}