Javascript 调用本机原型方法时扩展或继承对象原型
我一直在读,它在某处写道: 错误做法:本地原型的扩展 一个经常使用的mis特性是扩展Object.prototype或 另一个内置原型 这种技术被称为猴子修补和破坏封装。 虽然Prototype.js等流行框架使用,但仍然存在 没有很好的理由将内置类型与其他 非标准功能 扩展内置原型的唯一好理由是向后移植 更新的JavaScript引擎的特性;例如Array.forEach, 等等 在一个真实的示例中,我尝试使用angular服务来处理http请求,该服务返回一个简单的对象实例,其中包含几个属性和两个方法Javascript 调用本机原型方法时扩展或继承对象原型,javascript,angularjs,prototype,Javascript,Angularjs,Prototype,我一直在读,它在某处写道: 错误做法:本地原型的扩展 一个经常使用的mis特性是扩展Object.prototype或 另一个内置原型 这种技术被称为猴子修补和破坏封装。 虽然Prototype.js等流行框架使用,但仍然存在 没有很好的理由将内置类型与其他 非标准功能 扩展内置原型的唯一好理由是向后移植 更新的JavaScript引擎的特性;例如Array.forEach, 等等 在一个真实的示例中,我尝试使用angular服务来处理http请求,该服务返回一个简单的对象实例,其中包含几个属性
findAll()
和findOne(id)
,我将在ui路由器的解析方法中使用其中一个(并且只使用一次):
解析:{
资源:'资源',
所有图像:功能(资源){
var images=新资源(“图像”);
返回images.findAll();
},
singleImage:函数(资源){
var image=新资源(“图像”);
返回图像。findOne(4);
}
},
根据我将调用的两个方法中的哪一个,我将尝试使用另一个预定义的项
或集合来扩展(甚至替换)整个实例资源
,其中每个方法都有自己的结构和方法,因此在我的控制器中,我可以执行以下操作:
if(allImages.existNext())allImages.nextPage();
var currentPage=allImages.meta.currentPage,
收集=allImages.data;
singleImage.url='abc';
singleImage.save();
现在,我找到的唯一可行的解决方案(由一个与http请求无关的最小示例表示)是:
var myApp=angular.module('myApp',[]);
myApp.工厂(“动物”,动物);
功能动物(){
var Cat=函数(){
this.preferedfood='fish';
};
Cat.prototype.sayMiau=函数(){
console.log('Miau!')
};
var Dog=函数(名称){
this.dogName=名称;
};
Dog.prototype.sayGrr=函数(){
console.log('Grrr!')
};
功能动物(年龄){
这个。年龄=年龄;
}
动物原型={
makeItCat:function(){},
makeItDog:函数(名称){
狗。叫(这个,名字);
这个。uuuu proto_uuuu=Dog.prototype;
},
};
返回动物;
}
所以在控制器内部我可以做:
var-Dan=新动物(7);
Dan.makeItDog('Dan');
Console.log(Dan.age);//产出“7”
Console.log(Dan.dogName);//输出“Dan”
Dan.sayGrr();//输出“Grrr!”
正如你在这张照片上看到的
问题是:
对吗?我并没有破坏Object.prototype应该如何工作,或者失去它应该提供的性能增益?有更好的方法吗?例如,可能使用angular.extend
或根本不扩展(或替换)原型,而是使用类似以下内容:
var Dog=函数(名称){
this.dogName=名称;
this.sayGrr=函数(字符串){
console.log('Grrr!')
}
};
...
动物原型={
makeItCat:function(){},
makeItDog:函数(名称){
狗。叫(这个,名字);
},
};
我认为你这样做可能会奏效。我不确定你的工厂实施情况。我曾经做过类似的事情,可能会有所帮助:
查看工作界面
这是您的代码,只需稍加编辑:
var myApp = angular.module('myApp', []);
myApp.factory('AnimalFactory', AnimalFactory);
function AnimalFactory() {
// This is the main class
var Animal = function(age, fullName) {
this.age = age;
this.fullName = fullName;
this.eat = function() {
console.log('I am eating');
};
};
// Dog should inherit from Animal
var Dog = function(age, fullName) {
// Calling the animal constructor
Animal.call(this, age, fullName);
// Augmenting object adding a new method
this.bark = function() {
console.log('I am ' + this.fullName + ' and I bark Woof woof');
};
};
// Setting the Dog prototype to Animal
Dog.prototype = Object.create(Animal);
var Cat = function(age, fullName) {
// Calling the animal constructor
Animal.call(this, age, fullName);
// Augmenting object adding a new method
this.meow = function() {
console.log('I am ' + this.fullName + ' and I meow');
};
};
// Setting the Cat prototype to Animal
Cat.prototype = Object.create(Animal);
function createDog(age, fullName) {
return new Dog(age, fullName);
}
function createCat(age, fullName) {
return new Cat(age, fullName);
}
// Interface returned to use factory
return {
createDog: createDog,
createCat: createCat
};
}
function MyCtrl($scope, AnimalFactory) {
var dan = AnimalFactory.createDog(7, 'Dan');
dan.bark();
console.log(dan);
$scope.dan = dan;
}
我认为上面的代码在类之间有一个更清晰的原型继承实现。让我知道你的想法,这样我们可以改进它。回答得好。我还没有在我的真实示例中尝试过,但在阅读之后,我非常确定直接设置\uuuuuu proto\uuuu
不是一个好主意。在最初调用服务时设计继承布局和链接原型,然后在需要时使用new
关键字返回实例,这应该是一个比我更干净的解决方案。谢谢分享!确切地我认为您的示例可能有效,但此解决方案提供了一种更干净的方法。我非常高兴能帮助你@Salemourdani。问候语!