在JavaScript中是否可以创建新的数据类型?

29

在JavaScript中是否有可能创建一个像字符串(string)一样的新数据类型?

例如:我有一个变量person,我想声明该变量的类型为Person。

就像这样:

var person = "idk"
console.log(typeof person) 

输出:"人"


你可以定义一个类。typeof 是用于 "纯" JavaScript 类型的。 - SomoKRoceS
4
是的,使用类是可以实现的,尽管你创建的任何类typeof都会返回object。我有一种感觉,如果这是为了解决问题,可能会有更好的解决方案。您可以编辑您的帖子并进行澄清,以便我们能够给出更好的答案。 - dwb
实际上,您确实可以定义自定义类型,只是typeof有点,嗯,有点问题。请改用instanceof或实现自定义的.toString方法。 - rexfordkelly
7个回答

30

你可以最接近你所描述的方式是通过测试instanceof,或者使用instanceof来创建自己的类型检查函数:

class Person {
  constructor(name, age) {
    this.name = name; 
    this.age = age;
  }
}

const bill = new Person("Bill", 40);

function checkType(data){
  if(data instanceof Person) return "Person";
  return typeof data; 
}

console.log(bill instanceof Person);
console.log(checkType(bill));
console.log(checkType("bill")); 


16

仅有少数typeof返回值,可以在这里找到:

Undefined         "undefined"
Null              "object" (see below)
Boolean           "boolean"
Number            "number"
BigInt            (new in ECMAScript 2020)    "bigint"
String            "string"
Symbol            (new in ECMAScript 2015)    "symbol"
Function object   (implements [[Call]] in ECMA-262 terms)    "function"
Any other object  "object"

根据你的问题,你不能为 typeof 运算符设置自己的值。如果你使用 classfunction() 创建自己的对象,则其类型将是一个 object


6
我想指出,“我是否能创建自定义类型?”的答案是肯定的。但是你不能邀请typeof参加派对。
以下是一些解决方法和替代方案,以避免使用typeoftypeof有问题吗?
可以认为typeof运算符有点有问题……所以不会真正适用于“自定义”类型……实际上,它在JavaScript原始类型方面并不像你期望的那样工作。 typeof null // "object" ?! ok...,虽然这样做有其原因,但它并不直观
检查自定义类型的理想和“安全”方法是在自定义对象上定义和调用自定义toString方法。
你可以在MDN上阅读更多信息。 instanceof来拯救

不必使用typeof,您可以考虑使用instanceof。这将直接适用于您的“自定义”类,而无需执行任何其他操作,例如实现自己的.toString方法。

这里是一个简单的游乐场,演示基本思想...

class Person {}

p = new Person // An instance of Person

console.log(typeof p) // Object :(
console.log(p instanceof Person) // ture :P

// And with custom .toString method
Person.prototype.toString = function(){ return 'person' }

console.log(p.toString())        // 'person'
console.log(String(p))           // 'person'
console.log(p+"")                // 'person' <-- This is a simple coercive to string expression, employing our custom .toString method.
console.log(`${p}`)              // 'person' <-- using template literals
console.log([]+p)                // 'person' <-- coercion magic ... :p
console.log(""+{}+[":"]+p)       // "[object Object]:person"
console.log((typeof {})+' '+[p]) // "object person"

// BONUS ROUND --- we can even do "custom" JSON stringifications
Person.prototype.toJSON = function (){ return { typeof: '[object Person]'} }

console.log(JSON.stringify(p)) // "{"typeof":"[object Person]"}"

// Which works, as expected...
let agent = { agent: p }
console.log(JSON.stringify(agent)) // {"agent":{"typeof":"[object Person]"}}


5

1
在 JavaScript 的世界中,type 与其他面向对象编程语言不同。ECMA 和 JavaScript 之间存在微妙的差别:在 最新的 ECMA 中,只有 Undefined、Null、Boolean、String、Symbol、Number、BigInt 和 Object 这八种数据类型。也就是说,ECMA 将 Function 视为 Object 的一个子类型。在 JavaScript 中,我们几乎总是将 Function 视为一个单独的类型,因为 typeof (function(){}) 返回 function。但是,[] 的类型是 array,因此我们将 Array 视为 Object 的一个子类型,同样的情况也发生在 Set、Map、Date... 上,这些数据在某些面向对象编程语言(如 Python)中可能作为一个单独的类型存在,但在 JavaScript 中,它们都是 Object 的子类型。因此,在谈论 JavaScript 中的 type 时,这就是我们面对的真实情况。

但是,如果我们不仅仅关注于 typeof,在 JavaScript 中有更好的方法来创建和检测我们自己的新数据类型

准确地说,我们可以创建我们自己的新数据子类型,即 Object 类型的子类型,并且在大多数情况下,我们应该检测 JavaScript 数据的子类型。

关键是使用 Object.prototype.toStringsymbol.toStringTag

以下是演示代码:

function Person() {
}

const person = new Person()
const getObjTag = (obj) => Object.prototype.toString.call(obj).slice(8, -1)

console.log(getObjTag(person))  // log Object


Person.prototype[Symbol.toStringTag] = Person.name
console.log(getObjTag(person))  // log Person

// this method is reasonable in JS, because
console.log(getObjTag([]))  // log Array
console.log(getObjTag(new Set([])))  // log Set


0
你可以在ECMAScript 2015(ES6)之后将自定义类型定义为类(class)。
class Person {
  static get type() {
    return Person.prototype.constructor.name
  }
  get type() {
    return this.constructor.name
  }
  isA(clazz) {
    return this.type === clazz.type 
  }
}

const john = new Person();
if (john.isA(Person)) {
  console.log('John is a person')
}

然后你还可以定义自己的typeOf()函数:
const typeOf = (obj) => obj.type

console.log(typeOf(person))  // Prints 'Person' 

-2
你可以使用类来创建自定义对象。 但是,对于自定义数据类型,你不能真正做到这一点。
以下是一个基本示例:
class Person {
    constructor(name, age, nationality) {
        this._name = name;
        this._age = age;
        this._nationality = nationality;
    }

    info() {
        return `Hi ${this._name}, you're ${this._age} years old and your nationality is ${this._nationality}!`
    };
};

const person = new Person("John", 15, "British");
console.log(person.info())
console.log(typeof person)

在类中,您必须拥有constructor函数;如果没有,则JavaScript将插入一个空函数。

我对类不是很有经验(我刚开始使用它们),我建议您进一步研究它们-它们非常有用。


这不完全正确,参考链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString#Using_toString_to_detect_object_class - rexfordkelly
我对这些类的东西都很陌生。 - Static

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接