ホームページ  >  記事  >  ウェブフロントエンド  >  JS のプリミティブ型についてのより深い理解

JS のプリミティブ型についてのより深い理解

青灯夜游
青灯夜游転載
2021-02-02 18:01:442919ブラウズ

JS のプリミティブ型についてのより深い理解

JavaScript のプリミティブ型には、Unknown、Null、Number、Boolean、String が含まれます。その他の変数は参照型、つまりオブジェクト型です。プリミティブ型は「スタック メモリ」に保存され、参照型は「ヒープ メモリ」に保存されますが、通常、JavaScript で変数を使用する場合、メモリ内の変数の位置はあまり考慮されません。

「typeof」演算子は、変数値のデータ型を取得するために使用されます。 typeof は変数名またはリテラル値をオペランドとして受け入れ、変数の型情報を説明する文字列を返すことができます。 typeof の戻り値は JavaScript の型に対応していないことに注意してください。

  • # "unknown" - 変数値は未定義です

  • #"number" —— 変数値は数値です。

  • "boolean" —— 変数値はブール値です。

  • "string" —— 変数値は文字列です。

  • "object" —— 変数値はオブジェクトまたは null

  • " 関数です。 " ——変数の値は Function

また、typeof は関数ではなく (,-) のような演算子です。ただし、「typeof(12)」を使用しても問題は発生しません。エラーです。演算子「typeof 12」が適切な使用方法です。

1、未定義および null

ECMA-262 ドキュメントの未定義タイプの定義は次のとおりです:

未定義タイプは正確に次のとおりです。未定義と呼ばれる 1 つの値。値が割り当てられていない変数には値が未定義になります。 var を使用して宣言されていない変数の場合、var を使用するとエラーが生成されますが、typeof 演算子を使用すると「未定義」が返されます。

var foo;
alert(foo);        // undefined
alert(bar);        // 错误
alert(typeof foo); // undefined
alert(typeof bar); // undefined

unknown は (null のようなリテラル値ではなく) グローバル変数として実装されます。 )、その値は「未定義」です。 ECMAScript 3 では、unknown に他の値を割り当てることができ、ECMAScript 5 では読み取り専用に修正されました。

Null 型にも値は 1 つだけあり、null は「null 値」を表すために使用されます。ほとんどのプログラミング言語には、空の値を表すために使用される null や nil などのリテラルがあります。ただし、他のプログラミング言語とは異なり、JavaScript では、初期化されていない変数 (未定義で表される) の値を表すために null を使用しません。

null の論理的な意味は、null オブジェクト ポインターを表すことです。 JavaScript の通常のオブジェクトには単純なデータ型が含まれていないため、論理的に null とは、変数が null 値 (リテラル "{}" ではない) を持つオブジェクト型を指していることを意味します。

このため、null 値の型を取得するために typeof 演算子を使用すると、結果が「object」になる理由が理解できます。 JavaScript におけるオブジェクト型の null 値の意味は、数値型の 0、文字列型の "" と同様です。

unknown と null はどちらも「null 値」を表すために使用されますが、論理的な意味では、unknown の方が null よりも「低レベル」です。通常の状況では、変数値を明示的に未定義として指定する必要はありません。

オブジェクトを保存することを目的としているが、実際にはオブジェクトを指していない変数の場合、null オブジェクト ポインターとしての null の役割を反映し、未定義の変数と区別するために、変数値を null に設定する必要があります。 。

2. 数値

ECMAScript は単純化された数値モデルを使用します。別の整数型を分離することなく、数値型 Number を 1 つだけ持ちます。 Number 型は実装上、IEEE 754 規格で定義された 64 ビット倍精度浮動小数点形式を採用しています。 64 ビット浮動小数点形式では、52 ビットが仮数を表し、11 ビットが指数を表し、1 ビットが符号を表します。したがって、整数を表現する場合、JavaScript が表現できる整数の範囲は -Math.pow(2,53) から Math.pow(2,53) までとなり、この範囲を超えると、下位桁の数値の精度は保証されません。

var n = Math.pow(2,53); // 9007199254740992
alert(n === n + 1);     // true, 9007199254740992 + 1得到的值还是9007199254740992

実際の Web 開発では、バックグラウンドでの処理 (Java など) のために Long Int 型を Javascript に渡す必要がある場合、JavaScript が JSON データを Number 型に解析した後、重要: 最後の数桁が変更されています。

JavaScript は演算に浮動小数点値を使用するため、浮動小数点数を表すために IEEE 754 標準形式を使用する他のすべてのプログラミング言語と同様に、小数部分で精度の問題が発生します。コード内の小数部分での等価判定は避けてください。 (整数部分は正確です)

var a = 0.1;
var b = 0.2;
alert(a + b === 0.3); // false

値がJavaScriptが表現できる数値の上限を超えた場合(オーバーフロー)、それを表す無限大(または-Infinity、負の無限大)の値に自動的に変換されます。 infinity; 値が無限に 0 に近く、JavaScript 表現の範囲を超える (アンダーフロー) 場合、0 (または 0 と同じ -0) に設定されます。 JavaScript ではオーバーフロー エラーが発生しません (ゼロで除算する場合を含む)。

var a = Number.MAX_VALUE * 2;          //Infinity
var b = Number.MIN_VALUE / 2;          //0
var c = 1 / 0;                         //Infinity or NaN, 依JS执行环境不同
var d = 0 / 0;                         // NaN

Number 型は、数値ではない特別な値 NaN を定義します。 NaN の意味は、値が得られるべきところで値が得られないことを意味します。 NaN をオペランドとして使用する算術演算はすべて NaN になります。

另外NaN也是唯一一个使用对自身进行相等判断会得到false的数值。NaN的这个怪异之处破坏了JavaScript运算符的对称性。如果在代码中需要通过比较数值大小进行分支判断,就需要注意可能出现NaN的情况,因为使用NaN与其他数值进行大小比较总会得到false,而这可能不是你想要的结果。

var a = 10;   
a = a - "not number"         // NaN
alert(a === a);             // false
var b = 12 + a;              // NaN
var c = 10;
alert(b >= c || b < c);      // false

另一个Number类型中不常引人注目的地方是位运算。JavaScript中提供了按位操作运算符。在很多其他编程语言中,按位操作可以进行硬件级处理,所以非常快。

但是JavaScript没有整数类型,它的位操作是先把数值转换为32位整数,然后进行计算,然后再转换回去,JavaScript绝大部分运行环境是在浏览器中,与硬件相隔较远,因此位操作执行很慢。

3、字符串

与很多其他编程语言中一样,JavaScript中的字符串值也是不可变的,改变一个字符串变量的值,相当于重新生成了一个字符串并把它赋值给变量。JavaScript中的简单类型无法进行方法调用(作为this调用函数),但我们还是可以进行诸如

"abcdefg".toUpperCase();

这样的操作。这是因为JavaScript为简单数据类型提供了一种方式,把它们包装为对象类型,然后进行方法调用。”"abcdefg"“先被隐式地包装为对象,然后使用包装出的对象调用toUpperCase方法,待方法调用结束后,JavaScript再隐式地把包装对象回收。

其它简单数据类型也使用同样的方式。也可以使用JavaScript提供的构造函数显示地创建包装对象,JavaScript提供了String()、Number()和Boolean()三个构造函数,分别用于构建String、Number和Boolean类型的包装对象。

4、类型转换

ECMA-262中对数据类型的转换有详细的定义,很多JavaScript的参考资料也会列出类型转换的详细规则,这里就不再赘述了,下面只讨论一些值得注意的问题。

JavaScript有两组相等比较运算符:”===“和”!==“、”==“和”!=“。Crockford在著作《JavaScript:The Good Parts》里面列举的Bad Parts中的第一个就是”==“运算符。

原因在于”==“运算符会执行隐式的类型转换,而JavaScript中类型转换的规则又非常复杂,很容易导致代码中出现不易发现的bug。与”===“和其他编程语言中的”==“不同,JavaScript中的”==“运算符并不具备传递性: ∀x∀y∀z(x == y ∧ y == z → x == z)并不成立:

"" == "0";             // false
"" == 0;               // true
"0" == 0;              // true

Crockford和Zakas都建议不要使用“==”运算符,而使用“===”代替。若不遵循这个建议,使用“==”运算符时,请务必确保你明确知道两个比较变量的类型信息,以免发生预料之外的类型转换。

另外一个经常用到类型转换的地方是分支判断。if(和其它)语句并不要求进行分支判断的表达式结果必须为Boolean类型,而会根据特定的规则把判断表达式的结果转换为true或false后再进行判断。

if (obj !== undefined && obj !== null) {
    // code
}

// 上面的判断条件可以替换为

if (obj) {
    // code
}

上面代码中的obj代表一个对象变量,若其值为undefined或null,则被转换为false,反之转换为true。这种方式并不完全安全,若使用的变量是简单数据类型,就需要注意一些特殊值的转换规则,否则代码可能不会按照预想的方式执行。

if (typeof num === "number" && num) { 
    // if num is 0, get false
    //code
}

上面代码的本意是获取一个有效的数值类型,屏蔽了其他类型和num的值为NaN的情况(NaN会转换false)。但代码中有一个纰漏,它忽略了num值为0的情况。

0值会被转换为false,从而导致下面的代码不会被执行,这可能与编码者的本意相违背。同样使用String类型作为分支条件,也要考虑""会被自动转换为false的情况。

与分支判断中的类型转换相似的情况,是采用短路方式为变量赋值。由于JavaScript中”&&“和”||“操作符的特性,我们经常采用短路方式为变量赋值。

”&&“操作符会返回表达式中第一个可以转换为false的操作数或最后一个操作数(全为true时);”||“操作符返回表达式中第一个可以转换为true的操作数或最后一个操作数(全为false时)。

var obj = obj1 || obj2 || {}; 
var attr = obj && pro && attr;

与分支判断一样,需要警惕表达式中可能出现的特殊值:0,"",null等。

JavaScript的类型模型,提供了极大的灵活性的同时也带来了很多陷阱,编码过程中需要小心地规避这些陷阱,因为代码审查很容易忽略它们,出现问题时,它们也往往很难被发现。

更多计算机编程相关知识,请访问:编程入门!!

以上がJS のプリミティブ型についてのより深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はoschina.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。