Javascript 如何向(JSON)对象添加方法';什么是原型?
假设我从服务器接收到一些JSON对象,例如Person对象的一些数据:Javascript 如何向(JSON)对象添加方法';什么是原型?,javascript,json,prototype,Javascript,Json,Prototype,假设我从服务器接收到一些JSON对象,例如Person对象的一些数据: {firstName: "Bjarne", lastName: "Fisk"} 现在,我希望在这些数据之上有一些方法,例如,用于计算全名: fullName: function() { return this.firstName + " " + this.lastName; } 这样我就可以 var personData = {firstName: "Bjarne", lastName: "Fisk"}; var per
{firstName: "Bjarne", lastName: "Fisk"}
现在,我希望在这些数据之上有一些方法,例如,用于计算全名:
fullName: function() { return this.firstName + " " + this.lastName; }
这样我就可以
var personData = {firstName: "Bjarne", lastName: "Fisk"};
var person = PROFIT(personData);
person.fullName(); // => "Bjarne Fisk"
基本上我想在这里做的是向对象的原型添加一个方法。fullName()
方法是通用的,因此不应添加到数据对象本身。例如:
personData.fullName = function() { return this.firstName + " " + this.lastName; }
。。。会导致大量冗余;而且可以说“污染”了数据对象
将此类方法添加到简单数据对象的当前最佳实践方式是什么
编辑:
稍微偏离主题,但如果上面的问题可以解决,就可以像这样做一些很好的伪模式匹配:
if ( p = Person(data) ) {
console.log(p.fullName());
} else if ( d = Dog(data) ) {
console.log("I'm a dog lol. Hear me bark: "+d.bark());
} else {
throw new Exception("Shitty object");
}
如果数据
对象具有正确的属性,则人
和狗
将添加方法。如果不是,则返回falsy(即数据不匹配/不一致)
附加问题:有人知道使用或启用此功能(即使其变得简单)的库吗?它已经是javascript模式了吗?如果是,它叫什么;你有详细说明的链接吗?谢谢:)假设您的对象来自某个JSON库,该库解析服务器输出以生成对象,那么它的原型中通常不会有任何特殊的内容;为不同服务器响应生成的两个对象不会共享一个原型链(当然,除了Object.prototype;) 如果您控制从JSON创建“Person”的所有位置,您可以反过来做:创建一个“空”Person对象(在其原型中使用类似于fullName的方法),并使用JSON生成的对象(使用$.extend、u.extend或类似的方法)对其进行扩展
我认为用数据传输方法并不常见,但这似乎是个好主意 此项目允许您将函数与数据一起编码,但它不是标准的,当然需要使用相同的库进行解码
https://github.com/josipk/json-plus
如果您处理的是简单的JSON数据,那么每个person对象的原型将只是
object.prototype
。为了使它成为一个原型为Person.prototype
的对象,您首先需要一个Person
构造函数和原型(假设您以传统方式执行Javascript OOP):
然后,您需要一种将普通对象转换为Person对象的方法,例如,如果您有一个名为mixin
的函数,它只需将所有属性从一个对象复制到另一个对象,您可以执行以下操作:
//example JSON object
var jsonPerson = {firstName: "Bjarne", lastName: "Fisk"};
var person = new Person();
mixin(person, jsonPerson);
这只是解决问题的一种方法,但希望能给你一些想法
更新:现在
Object.assign()
在现代浏览器中可用,您可以使用它而不是编写自己的mixin函数。还有一个垫片可以使Object.assign()
在旧浏览器上工作;请参阅。匿名对象没有原型。为什么不干脆做这个:
function fullName(obj) {
return obj.firstName + ' ' + obj.lastName;
}
fullName(person);
如果绝对必须使用方法调用而不是函数调用,则始终可以使用对象执行类似的操作
var Person = function (person) { this.person = person; }
Person.prototype.fullName = function () {
return this.person.firstName + ' ' + this.person.lastName;
}
var person = new Person(personData);
person.fullName();
你可能不应该这样做 JSON允许序列化状态,而不是类型。因此,在您的用例中,您应该这样做:
var Person = function ( data ) {
if ( data ) {
this.firstName = data.firstName;
this.lastName = data.lastName;
}
};
Person.prototype.fullName = function ( ) {
return this.firstName + ' ' + this.lastName;
};
//
var input = '{"firstName":"john", "lastName":"Doe"}';
var myData = JSON.parse( input );
var person = new Person( myData );
换句话说,您希望更改现有对象的原型(也称为类)。 从技术上讲,您可以这样做:
var Person = {
function fullName() { return this.firstName + " " + this.lastName; }
};
// that is your PROFIT function body:
personData.__proto__ = Person ;
在此之后,如果您将在Person的personData实例上获得
true
,那么这里还有另一种可能性。接受第二个参数,该参数是用于从叶节点到根节点恢复遇到的对象的函数。因此,如果您可以根据类型的内在属性识别它们,那么您可以在一个reviver函数中构造它们。下面是一个非常简单的例子:
var MultiReviver = function(types) {
// todo: error checking: types must be an array, and each element
// must have appropriate `test` and `deserialize` functions
return function(key, value) {
var type;
for (var i = 0; i < types.length; i++) {
type = types[i];
if (type.test(value)) {
return type.deserialize(value);
}
}
return value;
};
};
var Person = function(first, last) {
this.firstName = first;
this.lastName = last;
};
Person.prototype.fullName = function() {
return this.firstName + " " + this.lastName;
};
Person.prototype.toString = function() {return "Person: " + this.fullName();};
Person.test = function(value) {
return typeof value.firstName == "string" &&
typeof value.lastName == "string";
};
Person.deserialize = function(obj) {
return new Person(obj.firstName, obj.lastName);
};
var Dog = function(breed, name) {
this.breed = breed;
this.name = name;
}
Dog.prototype.species = "canine";
Dog.prototype.toString = function() {
return this.breed + " named " + this.name;
};
Dog.test = function(value) {return value.species === "canine";};
Dog.deserialize = function(obj) {return new Dog(obj.breed, obj.name);};
var reviver = new MultiReviver([Person, Dog]);
var text = '[{"firstName": "John", "lastName": "Doe"},' +
'{"firstName": "Jane", "lastName": "Doe"},' +
'{"firstName": "Junior", "lastName": "Doe"},' +
'{"species": "canine", "breed": "Poodle", "name": "Puzzle"},' +
'{"species": "canine", "breed": "Wolfhound", "name": "BJ"}]';
var family = JSON.parse(text, reviver)
family.join("\n");
// Person: John Doe
// Person: Jane Doe
// Person: Junior Doe
// Poodle named Puzzle
// Wolfhound named BJ
var MultiReviver=函数(类型){
//todo:错误检查:类型必须是数组,并且每个元素
//必须具有适当的“测试”和“反序列化”功能
返回函数(键、值){
var类型;
对于(变量i=0;i
这取决于您是否能够明确地识别您的类型。例如,如果有其他类型,甚至是Person的子类型,也有firstName和lastName属性,这将不起作用。但它可能涵盖了一些新的领域
var Person = {
function fullName() { return this.firstName + " " + this.lastName; }
};
// that is your PROFIT function body:
personData.__proto__ = Person ;
var MultiReviver = function(types) {
// todo: error checking: types must be an array, and each element
// must have appropriate `test` and `deserialize` functions
return function(key, value) {
var type;
for (var i = 0; i < types.length; i++) {
type = types[i];
if (type.test(value)) {
return type.deserialize(value);
}
}
return value;
};
};
var Person = function(first, last) {
this.firstName = first;
this.lastName = last;
};
Person.prototype.fullName = function() {
return this.firstName + " " + this.lastName;
};
Person.prototype.toString = function() {return "Person: " + this.fullName();};
Person.test = function(value) {
return typeof value.firstName == "string" &&
typeof value.lastName == "string";
};
Person.deserialize = function(obj) {
return new Person(obj.firstName, obj.lastName);
};
var Dog = function(breed, name) {
this.breed = breed;
this.name = name;
}
Dog.prototype.species = "canine";
Dog.prototype.toString = function() {
return this.breed + " named " + this.name;
};
Dog.test = function(value) {return value.species === "canine";};
Dog.deserialize = function(obj) {return new Dog(obj.breed, obj.name);};
var reviver = new MultiReviver([Person, Dog]);
var text = '[{"firstName": "John", "lastName": "Doe"},' +
'{"firstName": "Jane", "lastName": "Doe"},' +
'{"firstName": "Junior", "lastName": "Doe"},' +
'{"species": "canine", "breed": "Poodle", "name": "Puzzle"},' +
'{"species": "canine", "breed": "Wolfhound", "name": "BJ"}]';
var family = JSON.parse(text, reviver)
family.join("\n");
// Person: John Doe
// Person: Jane Doe
// Person: Junior Doe
// Poodle named Puzzle
// Wolfhound named BJ
var myobj = {
title: 'example',
assets:
{
resources: ['zero', 'one', 'two']
}
}
var myfunc = function(index)
{
console.log(this.resources[index]);
}
myobj.assets.giveme = myfunc
myobj.assets.giveme(1);
Object.setPrototypeOf( personData, Person.prototype );