2013-08-06 2 views
13

Я пытаюсь разработать автономное приложение HTML5, которое должно работать в большинстве современных браузеров (Chrome, Firefox, IE 9+, Safari, Opera). Поскольку IndexedDB не поддерживается Safari (пока), а WebSQL устарел, я решил использовать localStorage для хранения созданных пользователем объектов JavaScript и JSON.stringify()/JSON.parse() для ввода или вытаскивания объектов. Однако я обнаружил, что JSON.stringify() не обрабатывает методы. Ниже приведен пример объекта с помощью простого метода:json.stringify не обрабатывает методы объекта

var myObject = {}; 
    myObject.foo = 'bar'; 
    myObject.someFunction = function() {/*code in this function*/} 

Если я stringify этот объект (а затем положить его в LocalStorage), все, что будет оставляется myObject.foo, не myObject.someFunction().

//put object into localStorage 
    localStorage.setItem('myObject',JSON.stringify(myObject)); 

    //pull it out of localStorage and set it to myObject 
    myObject = localStorage.getItem('myObject'); 

    //undefined! 
    myObject.someFunction 

Я уверен, что многие из вас, вероятно, уже знают об этом ограничении/функции/о том, что вы хотите назвать. Обходной путь, который я придумал, - создать объект с помощью методов (myObject = new objectConstructor()), вытащить свойства объекта из localStorage и назначить их новому созданному мне объекту. Я чувствую, что это окольный подход, но я новичок в мире JavaScript, так вот как я его решил. Итак, вот мой главный вопрос: я бы хотел, чтобы весь объект (свойства + методы) был включен в localStorage. Как мне это сделать? Если вы, возможно, покажете мне лучший алгоритм или, может быть, другой метод JSON, о котором я не знаю, я бы очень признателен.

+4

функции не существует в формате JSON. См .: http://json.org. –

+0

Вот что я подумал после прочтения спецификации, но есть ли у вас способ сохранить методы? Или мой способ, как вы это сделаете? – user2649759

+0

Возможный дубликат функции [JSON.stringify] (http://stackoverflow.com/questions/6754919/json-stringify-function) – Bergi

ответ

27

Функции в javascript - это не просто их код. У них также есть возможности. Код может быть сжатым, но область не может.

JSON.stringify() будет кодировать значения, поддерживаемые JSON. Объекты со значениями, которые могут быть объектами, массивами, строками, числами и булевыми. Все остальное будет игнорироваться или бросать ошибки. Функции не поддерживаются в JSON. JSON обрабатывает только чистые данные, функции - это не данные, а поведение с более сложной семантикой.


Сказали, что можете изменить способ работы JSON.stringify(). Второй аргумент - функция replacer. Таким образом, вы могли бы заставить поведение, которое вы хотите, заставляя strinigification функций:

var obj = { 
    foo: function() { 
    return "I'm a function!"; 
    } 
}; 

var json = JSON.stringify(obj, function(key, value) { 
    if (typeof value === 'function') { 
    return value.toString(); 
    } else { 
    return value; 
    } 
}); 

console.log(json); 
// {"foo":"function() { return \"I'm a function!\" }"} 

Но когда вы читаете, что еще в вам придется Eval функции строки и установить результат обратно к объекту, так как JSON делает не поддерживают функции.

Все функции кодирования в JSON могут быть довольно волосатыми. Вы уверены, что хотите это сделать? Вероятно, есть лучший способ ...

Возможно, вы могли вместо этого сохранить необработанные данные и передать их конструктору из вашего JS, загруженного на страницу. localStorage будет хранить данные только, но ваш код, загруженный на страницу, предоставит методы для работы с этими данными.

// contrived example... 

var MyClass = function(data) { 
    this.firstName = data.firstName; 
    this.lastName = data.lastName; 
} 

MyClass.prototype.getName() { 
    return this.firstName + ' ' + this.lastName; 
} 

localStorage.peopleData = [{ 
    firstName: 'Bob', 
    lastName: 'McDudeFace' 
}]; 

var peopleData = localStorage.peopleData; 

var bob = new MyClass(peopleData[0]); 
bob.getName() // 'Bob McDudeFace' 

Нам не нужно, чтобы сохранить метод getName() в localStorage. Нам просто нужно передать эти данные в конструктор, который предоставит этот метод.

+1

Хорошо, я понимаю, о чем вы говорите. Я просто хотел посмотреть, нет ли чего-то, чего я не видел. Я закончу просто хранение данных и передачу этих данных функции-конструктора. Спасибо, что поняли! – user2649759

+1

Ответ принят. – user2649759

+0

Отличный ответ! Просто думал, что я хотел бы добавить, что _contrived example_ следует уточнить: 'localStorage.peopleData = [{ ПгвЬЫате: 'Bob', LastName: 'McDudeFace' }];' должно быть: 'localStorage.peopleData = JSON.stringify ( [{ Firstname: 'Боб', ЬавЬЫате: '' McDudeFace }] );' То есть, _array объектов_, хранящихся в localStorage, необходимо преобразовать в строку JSON. – DanDan

0

Если вы хотите укрепить свои объекты, но у них есть функции, вы можете использовать JSON.stringify() со вторым параметром replacer. Чтобы предотвратить циклические зависимости от объектов, вы можете использовать var cache = [].

В нашем проекте мы используем lodash. Для генерации журналов мы используем следующую функцию. Может использоваться для сохранения объектов до localStorage.

var stringifyObj = function(obj) { 
 
    var cache = [] 
 
    return JSON.stringify(obj, function(key, value) { 
 
    if (
 
     _.isString(value) || 
 
     _.isNumber(value) || 
 
     _.isBoolean(value) 
 
    ) { 
 
     return value 
 
    } else if (_.isError(value)) { 
 
     return value.stack || '' 
 
    } else if (_.isPlainObject(value) || _.isArray(value)) { 
 
     if (cache.indexOf(value) !== -1) { 
 
     return 
 
     } else { 
 
     // cache each item 
 
     cache.push(value) 
 
     return value 
 
     } 
 
    } 
 
    }) 
 
} 
 

 
// create a circular object 
 
var circularObject = {} 
 
circularObject.circularObject = circularObject 
 

 
// stringify an object 
 
$('body').text(
 
    stringifyObj(
 
    { 
 
     myBooblean: true, 
 
     myString: 'foo', 
 
     myNumber: 1, 
 
     myArray: [1, 2, 3], 
 
     myObject: {}, 
 
     myCircularObject: circularObject, 
 
     myFunction: function() {} 
 
    } 
 
) 
 
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Смежные вопросы