【问题标题】:How does Javascript know what type a variable is?Javascript 如何知道变量是什么类型?
【发布时间】:2012-09-04 01:58:59
【问题描述】:

我不知道为什么我在过去几年从未问过自己这个问题,但突然间我无法为自己或谷歌找到任何答案。

众所周知,Javascript 没有变量类型。真是一件好事。 但它必须以某种方式确定类型并使用它。

var a = 1;
var b = 2.0;
var c = 'c';
var d = "Hello World!";

所以我们有一个 Integer、Double/Float、Character、String(可以拆成 char*)

我知道 JS 与运行时解释器一起工作,但考虑到逻辑和“类型”必须以任何方式实现..

那么 Javascript 解释器如何识别并在内部处理变量? 在我的想象中,假设我会编写 C++,我会想到一种模板和容器,以及一些重载运算符的逻辑,并尝试检查它到底是什么。但这并没有考虑到最后。

请与我分享你的知识:-)

【问题讨论】:

  • 嗯,变量没有类型,但值是。该规范仅描述了语言中的某些机制是如何工作的,它没有定义实现。通常你会发现像 "If Type(x) is String...". 这样的表达式
  • 再次..我没有问如何在运行时确定js程序中的类型。
  • 这不是一个真正的问题。如果您想了解内部结构,请查看源代码。
  • 在这种情况下,我会将我的投票从重复修改为非建设性。解释器如何跟踪变量及其元数据是一个实现细节,并且在不同的实现之间肯定会有所不同。

标签: javascript types


【解决方案1】:

JavaScript 根据值分配设置变量类型。例如,当 JavaScript 遇到以下代码时,它知道 myVariable 应该是 number 类型:

var myVariable = 10;

同样,JavaScript 会在下面的例子中检测到变量类型是字符串:

var myVariable = "Hello World!";

JavaScript 也比许多其他编程语言灵活得多。对于 Java 等语言,必须在创建变量时将其声明为特定类型,并且一旦创建,该类型就无法更改。这称为 strong typing。另一方面,JavaScript 允许随时更改变量的类型,只需分配一个不同类型的值(更好地称为 loose typing)。

以下示例是 JavaScript 中变量的完全有效使用。在创建时,变量显然是 number 类型。稍后将字符串分配给此变量会将类型从数字更改为字符串。

var myVariable = 10;
myVariable = "This is now a string type variable";

变量的数据类型是 JavaScript 脚本引擎对变量当前持有的数据类型的解释。一个字符串变量保存一个字符串;一个数字变量保存一个数字值,依此类推。然而,与许多其他语言不同的是,在 JavaScript 中,同一个变量可以保存不同类型的数据,所有这些都在同一个应用程序中。这是术语松散类型和动态类型所熟知的概念,这两者都意味着 JavaScript 变量可以根据上下文在不同时间保存不同的数据类型。

完整文章在这里:http://www.techotopia.com/index.php/JavaScript_Variable_Types

另一篇可能对您有所帮助的文章:http://oreilly.com/javascript/excerpts/learning-javascript/javascript-datatypes-variables.html

有用的链接:

ECMAScript Language Specification

ECMAScript BNF Grammar

JAVAScript BNF Gramar

【讨论】:

  • 结合@James Allardice 和你的答案,我是否理解它的bnf(backus naur 形式)和分配正确类型的语法?
  • @Stefan 我在答案末尾添加了一些有用的链接,您可能会感兴趣...
【解决方案2】:

我可以在ES5 spec 中找到的唯一有用的行是:

在本规范中,符号“Type(x)”用作“x 的类型”的简写,其中“type”是指本节中定义的 ECMAScript 语言和规范类型。

假设当运行时需要执行需要知道某个值的类型的操作时,它会根据grammar defined in the spec 为每种类型检查该值,直到找到匹配项.

例如,布尔文字的语法如下:

布尔文字 ::

  true 
  false

如果该值恰好是 true 或恰好是 false(例如,没有引号),那么该值是布尔类型。

【讨论】:

  • 结合@AlphaMale和你的答案,我理解它的bnf(backus naur形式)和分配正确类型的语法是否正确?
  • 语法定义了类型,运行时应该能够使用该语法来确定值的类型。
【解决方案3】:

JavaScript 本身确实有类型,并且在内部,每个赋值都会接收到适当的类型。在您的示例var foo = 2.0; 中,类型将为float。程序员不必担心太多(起初),因为 JS 是松散类型(!== 无类型)。
这意味着如果我要将数字字符串与浮点数进行比较,引擎会将字符串强制转换为数字,以便进行比较。

不过,松散类型语言和强类型语言之间的主要区别不是类型强制。在 C(++) 中转换为您需要的类型是很常见的,并且在某些情况下,值会自动转换为正确的类型(2/2.0 == 2.0/2.0 == 1.0 ==> int 隐式转换为浮点数)。松散类型语言和强类型语言之间的主要区别在于您声明了一个具有不同类型的变量:

int i = 0;//ok
//Later:
i = 'a';//<-- cannot assign char to int

而 JS 允许你这样做:

var i = 1;//int
i = 1.123;//float
i = 'c';//char, or even strings
i = new Date();//objects

但是,正如typeofinstanceofparseFloatparseInttoString 等函数/关键字...建议:有类型,它们只是更灵活一点。并且变量不限于单一类型。

【讨论】:

    【解决方案4】:

    想象实现的一种简单方法是,所有值都保存在对象中,所有变量都是指针……在 C++ 中:

    struct Value
    {
        int type;
        Value(int type) : type(type) { }
        virtual ~Value() { }
    
        virtual std::string toString() = 0;
    };
    
    struct String : Value
    {
        std::string x;
        String(const std::string& x) : Value(STRING_TYPE), x(x) { }
        virtual std::string toString()
        {
            return x;
        }
    };
    
    struct Number : Value
    {
        double x;
        Number(double x) : Value(NUMBER_TYPE), x(x) { }
        ...
    };
    
    struct Object : Value
    {
        // NOTE: A javascript object is stored as a map from property
        //       names to Value*, not Value. The key is a string but
        //       the value can be anything
        std::map<std::string, Value *> x;
        Object() : Value(OBJECT_TYPE), x(x) { }
        ...
    };
    

    例如,每当必须执行操作时(例如a+b),您需要检查变量所指向的对象的类型以决定要执行的操作。

    请注意,这是一个非常简单的解释...今天的 javascript 比这更复杂和优化,但您应该能够大致了解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-03
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      • 2012-02-29
      • 2012-08-01
      • 1970-01-01
      相关资源
      最近更新 更多