Learning a programming language has only two aspects: one is syntax and the other is data type. The syntax of C-like languages is nothing more than if, while, for, functions, arithmetic operations, etc., and object-oriented languages are added to object.
Syntax is just a set of rules that language designers have made in advance. The grammar of different languages is different, but they all have some common points. For those who are familiar with one or two programming languages, grammar is often not a problem when learning other programming languages (of course, if you have been learning C-like languages, then it will definitely take some time to get involved in Lisp for the first time). The focus of learning is often on data types and related operations, and there is no old saying: "Data structure + algorithm = program"! Secondly, the syntax of some languages itself has design problems (javascript is even more so), so we don’t need to dig into these points. Of course, if you claim to be geek, you can play with it.
This article will give a detailed introduction to the data types in javascript.
Weak type vs strong type
Given the design philosophy of javascript, javascript is designed as a weak language.
Speaking of this, it is inevitable to talk about the difference between weak types and strong types.
Some people mistakenly think that the difference between the two is that "a strongly typed language needs to indicate its type when declaring a variable, while a weakly typed one does not use it." In fact, this view is wrong. For example, the following Java code snippet:
The code copy is as follows:
String s = "hello";
int l = s.getBytes().length;
How does the compiler know that .length is a legal expression? This is because the compiler knows that s's data type is String. When the getBytes method of String is called, the data type of the return value is byte[], so .length is a legal expression.
The real difference between the two is:
In strongly typed languages, the type of each expression can be determined at compile time and only operations that apply to that type are allowed;
Weak type languages allow any operation to be imposed on any type, but this operation may report an error at runtime.
Data Type
According to the specification of ECMAScript 5.1, there are six data types in JavaScript, namely: Undefined, Null, Boolean, Number, String, and Object. The first five belong to basic types, and the last belongs to object types.
Basic data types
The Undefined type has only one value, which is undefined, which means "null value", which applies to all data types.
The Null type has only one value, which is null, which means "no object" and only applies to object types.
Boolean type has two values, true and false
Values of type Number are sets of 64-bit floating-point numbers that follow the IEEE 754 standard, similar to Java's double. There is no integer data structure. In addition, there are three special values: NaN, Infinity, -Infinity
A value of type String is a collection of finite Unicode characters. Must be enclosed with 'or'.
null and undefined
Both null and undefined represent the concept of "non-value", if it is strictly distinguished:
- null means empty
- undefined means that it does not exist. This value is all the variables without initialization, missing parameters in the function, and no explicit return value.
In other languages, only one null is used to represent null values. Why is there an undefined in JavaScript? This is caused by historical reasons:
Javascript adopts Java syntax, divides types into basic types and object types. In Java, null is used to represent empty objects, and javascript inherits them for granted; in C language, null is 0 when converted to a number, and javascript also adopts the same method:
The code copy is as follows:
> Number(null)
0
> 5 + null
5
In javascript 1.0, there is no exception handling yet. For some exceptions (no initialized variables, missing parameters when calling functions, etc.), they need to be marked as a special value. null is a good choice, but Brendan Eich wants to avoid the following two things:
- This special value should not have a reference attribute, because it is object-specific
- This special value should not be converted to 0, because it is not easy to detect errors in the program
For these two reasons, Brendan Eich chose undefined, which can be forced to NaN.
The code copy is as follows:
> Number(undefined)
NaN
> 5 + undefined
NaN
The results are very different when dealing with JSON objects:
The code copy is as follows:
> JSON.parse(null)
null
> JSON.parse(undefined)
//Firfox SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
//Chrome SyntaxError: Unexpected token u
> JSON.stringify(null)
"null"
> JSON.stringify(undefined)
undefined
Object Type
As a scripting language, JavaScript itself has very streamlined functions, and many functions (file reading and writing, networking, etc.) are provided by the host environment. The bridge between the host environment and the javascript language is objects. The host environment provides a variety of functions by providing a series of objects that conform to the javascript syntax.
In this article in JavaScript object-oriented programming (if you don't know what a prototype is, I strongly recommend reading this article), I have repeatedly emphasized that objects are a series of key-value pairs in JavaScript, just like HashMap in Java. However, the properties of objects in JavaScript can have some descriptors (property descriptors), which is not available in HashMap.
Attribute descriptor
Attribute descriptors are divided into two categories:
Data descriptor (data descriptor), contains a series of boolean values, to indicate whether the attribute allows modification and deletion.
Accessor descriptor, including get and set functions.
Both descriptors are objects, and they both have the following two boolean properties:
configurable is used to specify whether the descriptor allows modification and deletion. Default is false.
enumerable is used to specify whether to access the property when it is traversing an object (using the for...in loop or the Object.keys method). Default is false.
In addition to the two common attributes above, the data descriptor has the following two attributes:
- value is used to specify the value of this property, default is undefined
- writable is used to specify whether the value of the property allows the change of the value of the property. The default is false
There are two properties for access descriptors:
- get is used to specify the accessor (getter, essentially a function) when accessing the property, and the return value of the accessor is the value of the property. Default is undefined
- set is used to specify the evaluator (setter, essentially a function) when accessing this property. The evaluator accepts a parameter. Default is undefined
We can use Object.defineProperty to set the object's property descriptor. For example:
The code copy is as follows:
// using __proto__
Object.defineProperty(obj, 'key', {
__proto__: null, // no inherited properties
value: 'static' // not enumerable
// not configurable
// not writable
// as defaults
});
From the above example, we can see that descriptors have the characteristics of inheritance. We explicitly set the __proto__ of the descriptor object to null, which avoids inheriting the corresponding attributes from Object.prototype. Of course, we can also explicitly set all properties of the descriptor:
The code copy is as follows:
// being explicit
Object.defineProperty(obj, 'key', {
enumerable: false,
configurable: false,
writable: false,
value: 'static'
});
This effect is the same as the first piece of code.
Here is another example of access descriptor:
The code copy is as follows:
// Example of an object property added with defineProperty with an accessor property descriptor
var bValue = 38;
Object.defineProperty(obj, 'key', {
get: function() { return bValue; },
set: function(newValue) { bValue = newValue; },
enumerable: true,
configurable: true
});
It should be noted that access descriptors and data descriptors cannot be confused. It is wrong to write the following:
The code copy is as follows:
// You cannot try to mix both:
Object.defineProperty(obj, 'conflict', {
value: 0x9f91102,
get: function() { return 0xdeadbeef; }
});
// throws a TypeError: property descriptors must not specify a value
// or be writable when a getter or setter has been specified
typeof
If you want to know the type of a variable at runtime, you can use the typeof operator. The return value of typeof is as follows:
One thing that needs to be noted is typeof null == "object". According to the ECMAScript 5.1 standard, the Null type should be a basic type. Why is object returned here? The reason is this:
In javascript 1.0, the value in javascript is represented by a structure such as a type tag and an actual value. The type flag of the object is 0, and null represents a NULL pointer (0x00) in C language, so the type flag of null is 0.
The above is the entire content of this article. Please refer to it if you need it.