Javascript 保存到本地存储时保留实例类型

Javascript 保存到本地存储时保留实例类型,javascript,Javascript,我很难弄清楚应该如何将类保存到,比如当我检索回来时,我仍然可以调用我定义的实例方法 下面是一个抛出错误的示例: class Employee { constructor(name, gender, department, yy, email) { this.name = name; this.gender = gender; this.department = department; this.email = email;

我很难弄清楚应该如何将类保存到,比如当我检索回来时,我仍然可以调用我定义的实例方法

下面是一个抛出错误的示例:

class Employee {
    constructor(name, gender, department, yy, email) {
        this.name = name;
        this.gender = gender;
        this.department = department;
        this.email = email;
        this.skills = [];
    }

    addNewSkill(skill){
        this.skills.push(skill);
    }
}

const employee = new Employee({
    name: "John Doe", 
    gender: "male", 
    department: "CS", 
    email: "john@doe.com"
});

employee.addNewSkill("coding");

localStorage.setItem("employees", employee);

const retrievedEmployee = JSON.parse(localStorage.getItem("employee"));

// Throws Uncaught TypeError: retrievedEmployees[0].addNewSkill is not a 
// function.
retrievedEmployee.addNewSkill("reading");

正如Nik Kyriakides在评论中所说,你可以这样做。它将被用作:

const Employee = require('./path/to/Employee.js');

const employee = new Employee('Jane Doe', 'Female', 'Development', 'jdoe@acme.com', [ 'html', 'css' ]);
employee.addNewSkill('javascript');
console.log(employee.skills);
或者,您可以使用setter:

...
set skills (skill) {
    this.skills.push(skill);
}
...
然后将其用作:

const Employee = require('./path/to/Employee.js');

const employee = new Employee('Jane Doe', 'Female', 'Development', 'jdoe@acme.com', [ 'html', 'css' ]);
employee.skills = 'javascript';
console.log(employee.skills);
但从语法上看,这看起来似乎应该设置数组,而不是附加到数组中,因此对于这种上下文来说,这可能不是一个好的选择。我确实想在这里提到它,以便让您了解如何获取和设置其他类变量


在您的示例中,我将按照以下方式进行设置:

Employee.js

module.exports = class Employee {
    constructor(name, gender, department, yy, email, skills) {
        this.name = name;
        this.gender = gender;
        this.department = department;
        this.email = email;
        this.skills = [];
    }

    addNewSkill(skill){
        this.skills.push(skill);
    }
}
然后,为了处理您的员工列表,我会这样做,这可能需要一些调整,但只是给您一个想法:

index.js

const Employee = require('./path/to/Employee.js');

const fs = require('fs');
const employees = fs.readFileSync('employees.txt').toString().split("\n");
let employeeList = [];
employees.forEach(employeeData => {
    const employee = JSON.parse(employeeData);
    const { name, gender, department, email, skills } = employee;
    employeeList.push(new Employee(name, gender, department, email, skills));
})

//do stuff with employeeList

使用
JSON.stringify
将对象转换为字符串时,对象将丢失其类型。虽然保留了它们的属性和值,但有关它是
员工
实例的任何信息都将丢失

window.localStorage
检索后,当您
JSON.parse
保存的字符串时,您创建的是普通对象,而不是实际的
Employee
对象,因此检索到的对象缺少
Employee.addNewSkill()
方法

您应该确保您的
Employee
类允许使用类似
Employee
的对象轻松实例化,然后每次从LocalStorage检索保存的员工时,都要从该对象中实例化一个新的
Employee
实例,如下所示:

下面是一个例子:

// The Employee now takes an Employee or Employee-like object 
// instead of separate arguments.
class Employee {
    constructor({ name, gender, department, yy, email, skills }) {
        this.name = name;
        this.gender = gender;
        this.department = department;
        this.email = email;
        this.skills = skills || [];
    }

    addNewSkill(skill){
        this.skills.push(skill);
    }
}

// Create an Employee.
const employee = new Employee({
    name: "John Doe", 
    gender: "male", 
    department: "CS", 
    email: "john@doe.com"
});

// Add a skill.
employee.addNewSkill("coding");

// Turn employee to string and save to localStorage.
localStorage.setItem("employee", JSON.stringify(employee));

// Parse the string back into an Employee-like object and 
// use that object to construct a new Employee.
const retrievedEmployee = new Employee(JSON.parse(localStorage.getItem("employee")))

// Add another skill, using the Employee instance method.
retrievedEmployee.addNewSkill("reading");

// Logs Employee having 2 skills, one added *before* we saved to localStorage 
// and another skill we added *after* we retrieved him from localStorage.
console.log(retrievedEmployee);

作为记录,我以前在largeish项目中遇到过这个问题,并使用了一个名为npm的模块,该模块允许序列化和反序列化自定义类型。

您的语法很好;在实例化一个新的
employee
之后,只需调用
employee.addNewSkill('coding')
,它就会在
employee.skills
数组中推送(添加)传递的
skill
参数。问题是什么?请添加有关您的代码在尝试执行时当前正在执行的操作的信息,以及它给您带来的错误,以便我们可以更好地帮助您当我实例化一名新员工时,我可以将其推入技能数组,但在现有员工中,我不能。我正在控制台中进行测试。您上下文中的“现有”员工是您从
localStorage
获取的员工?确实是@NikKyriakidesI我认为问题在于序列化/反序列化。反序列化的雇员是普通对象,而不是实际的
Employee
s,因此他们缺少
addNewSkill
方法。是的,你可能是对的。正如我所理解的,在解析对象时,它们会丢失它们的方法。Hmmm@NikKyriakides请参见在我的使用示例中,我如何要求该类,创建该类的新实例,然后修改该实例?您也可以对缓存在本地存储中的员工执行同样的操作,这应该是可行的。只需确保类文件导出该类。否则require()将不起作用,您不需要将addSkill方法存储到员工的本地缓存中;只需存储创建Employee实例所需的值。我认为OP不会使用
require
,也不会使用Node。OP似乎与浏览器代码一起工作。@Benjaminielsen使偶然发现这一点并有相同问题的人变得更简单;如果你愿意,我可以回滚。不,没关系,只是要弄清楚原因。我非常感谢你的帮助!:)