// Extending the Storage object:
Storage.prototype.setObject = function(key, value) {
this.setItem(key, JSON.stringify(value));
}
Storage.prototype.getObject = function(key) {
var value = this.getItem(key);
return value && JSON.parse(value);
}
// START HERE:
var dog = {
name : '',
woof : function(){ console.log('woof woof, I am ' + this.name); }
}
dog.name = 'Lovely';
//Store in the localstorage
localStorage.setObject('mydog', dog);
//Get from the localstorage
var mydog = localStorage.getObject('mydog');
console.log(mydog.name); // prints 'Lovely'
console.log(mydog.woof()); // ootest.html:36 Uncaught TypeError: mydog.woof is not a function(…)
为什么我收到错误?
答案 0 :(得分:2)
LocalStorage仅支持字符串。您可以使用JSON编码存储对象,但这对您的函数不起作用。
JSON仅支持数字,字符串,布尔值,数组和基本对象结构。
答案 1 :(得分:1)
let Dog = function(name) {
this.name = name
}
Dog.prototype.woof = function woof() {
console.log('woof woof, I am ' + this.name);
}
// Create a 'static' method for a Dog 'class'
Dog.fromJSON = function fromJSON(json) {
return new Dog(JSON.parse(json).name)
}
// Instantinate your objects with `new` keyword
let dog = new Dog('Lovely')
dog.woof()
let storedDog = JSON.stringify(dog)
console.log('stored:', storedDog)
// Dog.fromJSON() returns new Dog object,
// with the same parameters for a constructor
// and with all methods
let restoredDog = Dog.fromJSON(storedDog)
restoredDog.woof()
这种方法仅适用于与使用类似构造函数参数创建的行为相似的对象。如果您想在其中存储包含丰富数据的对象,请参阅How come JSON can't save object's functions?接受的答案。
可以通过Function对象在运行时从字符串创建函数。要创建函数,我们需要传递参数和正文:
new Function ([arg1[, arg2[, ...argN]],] functionBody)
要获取方法params和body,我们需要在方法上调用继承的toString()
方法:
dog.woof.toString()
能在字符串中存储功能声明,能从字符串创建功能。接下来的步骤是:将常规函数存储实现为对象属性,实现从JSON字符串恢复保存的函数。
下面的代码段中的脏工作实现示例。
安全风险。有人可以使用任意代码破解序列化函数。
糟糕的代码设计。拥有没有预定义构造函数的对象会导致维护地狱,因为你不能用javascript duck typing来对对象行为做出假设。
版本控制。如果更新代码,则无法确定客户端上存储的对象版本。
let dog = {
name : '',
woof : function() {
console.log('woof woof, I am ' + this.name);
}
}
dog.name = 'Lovely';
dog.woof()
let storedDog = saveWithFuncToJSON(dog)
console.log('stored:', storedDog)
let restoredDog = restoreWithFuncFromJSON(storedDog)
restoredDog.woof()
console.log("Don't use this approach in production!")
// Code below is created only for fun,
// if you need this code in production,
// then your code smells
// Return JSON string
function saveWithFuncToJSON(object) {
// Use Object.assign() just for simplicity,
// something more solid needed for real object copying
let preparedObject = Object.assign({}, object)
for (let prop in preparedObject) {
if (typeof(preparedObject[prop]) !== 'function') continue
// Different platforms constructing function string in different ways
// so you'll have to put a lot of efforts to make it work stable
let funcStr = preparedObject[prop].toString()
let startParams = funcStr.indexOf('(') + 1
let endParams = funcStr.indexOf(')')
let hasParams = (endParams - startParams)
let funcParams = !hasParams ? [] : funcStr.slice(
funcStr.indexOf('(') + 1,
funcStr.indexOf('\n')
).split(',')
let funcBody = funcStr.slice(
funcStr.indexOf('{') + 1,
funcStr.lastIndexOf('}')
)
// This is the most interesting part
// We will store function as a string like freezing humans
preparedObject[`__${prop}Func`] = {
params: funcParams,
body: funcBody
}
}
return JSON.stringify(preparedObject)
}
function restoreWithFuncFromJSON(jsonSting) {
let object = JSON.parse(jsonSting)
for (let prop in object) {
// Functions to be restored should be named differently
let shouldConvertToFunc = prop.startsWith('__') && prop.endsWith('Func')
if (!shouldConvertToFunc) continue
let funcName = prop.slice(2, -4)
let funcData = object[prop]
let contructorArgsArray = funcData.params.concat([funcData.body])
// Function() does all work for us
object[funcName] = Function.apply(null, contructorArgsArray)
delete object[prop]
}
return object;
}