2013-04-19 4 views
1

Является ли это хорошим/безопасным кросс-браузерным способом реализации метода переопределения в JavaScript? :Переопределение методов в JavaScript с конструкторским свойством

function Person(firstName, lastName) 
{ 
    this.firstName = firstName; 
    this.lastName = lastName; 
}; 

Person.prototype.sayHi = function() 
{ 
    return "Hi, my name is " + this.firstName; 
}; 

function Employee(firstName, lastName, position) 
{ 
    Person.call(this, firstName, lastName); 
    this.position = position; 
}; 

Employee.prototype = Object.create(Person.prototype); 

Employee.prototype.sayHi = function() 
{ 
    return this.constructor.prototype.sayHi() + " I'm a " + this.position; 
} 

Я мог бы также написать:

Employee.prototype.sayHi = function() 
{ 
    return Person.prototype.sayHi() + " I'm a " + this.position; 
} 

, но с этим решением я ссылаюсь к прямому методу, или

Employee.prototype.sayHi = function() 
{ 
    return this.__proto__.sayHi() + " I'm a " + this.position; 
} 

, но этот ужасный и не броузерах.

EDIT: Я предположил, Object.create является броузерами, как я могу использовать подкладку

+1

В JavaScript нет такой вещи, как «перегрузка метода». Я думаю, вы имеете в виду «переопределение» в этом случае, но в JS тоже нет такой вещи. –

+0

извините, опечатка: переопределение – dragonfly

ответ

1

Вы не должны полагаться на constructor свойство prototype позвонить поскольку обычно это свойство должно указывать на конструктор children.

Employee.prototype = Object.create(Person.prototype); 
Employee.prototype.constructor = Employee; 

Есть несколько других способов доступа родительских функций безопасно, как и со ссылкой на parent прототип непосредственно, как вы пытаетесь сделать в вашем втором примере, однако есть что-то не так с тем, как вы делаете это.

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

Employee.prototype.sayHi = function() { 
    return Person.prototype.sayHi.call(this) + " I'm a " + this.position; 
}; 

Другим способом сделать это было бы сохранить ссылку на родительском прототип в детях прототипе.

Employee.prototype.super = Person.prototoype; 

Employee.prototype.sayHi = function() { 
    return this.super.sayHi.call(this) + " I'm a " + this.position; 
}; 

Еще один интересный подход, который я видел, чтобы обернуть каждую функцию детей прототипа функции, которая динамически устанавливает ссылку на материнскую функцию на экземпляре объекта, так что вы можете использовать только this.parent() для вызова функция. Однако я бы не рекомендовал это решение, так как это уменьшит производительность и увеличит использование памяти.

Я создал jsFiddle, чтобы продемонстрировать эту концепцию.

1

No.

Employee.prototype = Object.create(Person.prototype); 

Object.create не поддерживается старыми браузерами, но вы можете Призонную шайбу Это.

Employee.prototype.sayHi = function() { 
    return this.constructor.prototype.sayHi() + " I'm a " + this.position; 
} 

Я бы не использовать. Вы ожидаете, что this.constructor будет Person, из которого вы унаследовали, но это может быть не так. На самом деле было бы неплохо установить Employee.prototype.constructor = Employee, что вызовет рекурсию с переполнением стека в ваш метод.

Вместо этого, вы должны явно ссылаться на функцию вы хотите использовать:

return Person.prototype.sayHi.call(this) + " I'm a " + this.position; 

Если вы хотите его динамически, вы будете использовать

return Object.getPrototypeOf(Employee.prototype).sayHi.call(this) + " I'm a " + this.position; 

но обратите внимание, что Object.getPrototypeOf не поддерживается более старые браузеры. Так что если вам нужен кросс-браузер и сухим способом, используйте шаблон модуля:

(function(proto, super) { 
    proto.sayHi = function() { 
     return super.sayHi.call(this) + " I'm a " + this.position; 
    }; 
    … 
})(Employee.prototype, Person.prototype); 

или разоблачающий образец прототипа:

Employee.prototype = (function(super) { 
    var proto = Object.create(super); 
    proto.sayHi = function() { 
     return super.sayHi.call(this) + " I'm a " + this.position; 
    }; 
    … 
    return proto; 
})(Person.prototype); 
Смежные вопросы