The introduction
After more than two months of intermittent reading of JavaScript classic little Red Book – JavaScript Advanced Programming (4th edition)
After reading it in detail, I found that the whole book is full of knowledge, and at first glance, the details of each chapter are slightly vague.
So I urge myself to plan to write the focus of each chapter to deepen my impression and understanding, and record what I have learned, thought and understood. To facilitate their own use of the computer’s quick search keywords for rapid positioning and learning, but also hope to help students in need.
If you want to learn systematically and carefully, of course, or read the original book is better, I also strongly recommend oh! The content here is for personal review and summary only.
Hint: some of the chapters that are not personally important or popular will be cut
3. Language basics
Ecma-262 defines JavaScript syntax, operators, data types, and built-in functionality in a pseudo-language called ECMAScript. By the end of 2017, most major browsers had almost or fully implemented this version of the specification, so this chapter is based on ECMAScript version 6.
3.1 grammar
ECMAScript’s syntax borrows heavily from C and other C-like languages such as Java and Perl.
3.1.1 Case sensitive
Everything is case sensitive in ECMAScript, be it variables, function names, or operators. Similarly, Typeof cannot be used as a function name (because it is a keyword), but Typeof is a perfectly valid function name.
3.1.2 identifier
An identifier is the name of a variable, function, attribute, or function parameter. Can consist of one or more of the following characters:
- The first character must be a letter, underscore (_), or dollar sign ($).
- The remaining characters can be letters, underscores, dollar signs, or numbers.
The letters in the identifier can be extended ASCII letters or Unicode alphabetic characters (but not recommended).
ECMAScript identifiers use camelcase, that is, the first letter of the first word is lowercase and the first letter of each subsequent word is capitalized. Examples: firstSecond, myCar.
Keywords, reserved words, true, false, and NULL cannot be used as identifiers.
3.1.3 annotation
ECMAScript uses C-style comments, including single-line and block comments.
-
// Single-line comment Copy the code
-
/* This is a multi-line comment */ Copy the code
3.1.4 Strict Mode
ECMAScript 5 adds the concept of strict schemas. Some non-standard writing of ECMAScript 3 is handled in this mode and errors are thrown for unsafe activities.
Add this line to the beginning of the script file to declare: “Use strict”; (a preprocessing instruction)
We can also specify a separate function to execute in strict mode by placing the preprocessor at the beginning of the function body:
function doSomething() {
"use strict";
/ / the function body
}
Copy the code
Strict mode affects many aspects of JavaScript execution and is supported by all modern browsers.
3.1.5 statement
-
A semicolon
-
let sum = a + b // No semicolon is recommended Copy the code
-
let diff = a - b; // A semicolon is recommended Copy the code
- Letting the parser determine where the statement ends helps prevent problems caused by ellipsis.
- Parsers try to fill in semicolons in the right places to correct syntax errors, which can help improve performance in some cases.
-
-
Code block: Begins with an open curly brace ({) and ends with a close curly brace (}).
-
if (test) // Single statements are valid, but not recommended console.log(test); Copy the code
-
if (test) { / / recommend console.log(test); } Copy the code
- Using blocks of code in control statements makes the content clearer and reduces the likelihood of errors.
-
3.2 Keywords and Reserved Words
Ecma-262 describes a set of reserved keywords that serve a specific purpose. Reserved keywords cannot be used as identifiers or attribute names.
All the keywords specified in ecMA-262 version 6 are as follows:
break do in typeof case else instanceof var
catch export new void class extends return while
const finally super with continue for switch yield
debugger function this default if throw delete import try
Reserved words for the future, although they have no specific use in the language, are reserved for the future as keywords.
-
Always keep
-
enum
-
-
Reserved in strict mode
-
implements package public
interface protected static
let private
-
-
Reserved in the module code
-
await
-
3.3 variable
ECMAScript variables are loosely typed, which means they can be used to hold any type of data. There are three keywords to declare variables: var, const, and let. Var is available in all versions of ECMAScript, while const and let are available only in ECMAScript 6 and later.
3.3.1 Var Keyword
var message; // Define a variable named message, which can be used to hold any type of value. (Uninitialized, the variable holds a special value called undefined)
var message = "hi";
message = 100; // Valid, but it is not recommended to change the type of the data value
var messgae = "hi",
found = false,
age = 29; // If you need to define more than one variable, separate each variable with a comma in a single statement
Copy the code
3.3.1.1 VAR Specifies the scope
A variable defined using the var operator becomes a local variable of the function that contains it.
function test() {
var message = "h1"; // Local variables
}
test();
console.log(message); / / error
Copy the code
3.3.1.2 VAR Declaration promotion
Variables declared by the var keyword are automatically promoted to the top of the function scope:
function foo() {
console.log(age);
var age = 26;
}
foo(); // undefined
// There is no error because the equivalent is as follows
function foo() {
var age;
console.log(age);
age = 26;
}
foo(); // undefined
// Therefore, you can use var to declare the same variable multiple times without any problem; the latter will override the former.
function foo() {
var age = 16;
var age = 26;
var age = 36;
console.log(age);
}
foo(); / / 36
Copy the code
3.3.2 rainfall distribution on 10-12 let statement
The let keyword declaration is similar to var, but with a very important difference. The most obvious difference is that the scope of the LET declaration is block scope, while the scope of the VAR declaration is function scope.
// Function scope
function foo() {
if (true) {
var name = 'Matt';
console.log(name); // Matt
}
console.log(name); // Matt
}
foo();
// block scope
function foo() {
if (true) {
let age = 26;
console.log(age); / / 26
}
console.log(age); // ReferenceError: Age is not defined
}
Copy the code
Let also does not allow duplicate declarations with a block scope.
var name;
var name; // No error will be reported
let age;
let age; // SyntaxError: The age identifier is already declared
var name;
let name; // SyntacError
Copy the code
3.3.2.1 Temporary dead zone
Variables declared by let are not promoted in scope. When parsing code, the JavaScript engine also pays attention to the let declaration that appears after the block, and the moment of execution before the LET declaration is known as the “temporal dead zone,” in which references to any variable declared later will throw an error.
console.log(name); // undefined
var name = 'Matt';
console.log(age); // ReferenceError: Age is not defined
let age = 26;
Copy the code
3.3.2.2 Global Declaration
var name = 'Matt'; // var declares variables that become properties of the window object
console.log(window.name); // 'Matt'
let age = 26; // let declared variables do not
console.log(window.age); // undefined
Copy the code
Let declarations still occur in global scope, and the corresponding variables persist for the life of the page. So to avoid syntaxErrors, you must ensure that the page does not declare the same variable twice.
Let declaration in 3.3.2.4 for loop
Like block scopes like for, for-in, and for-of loops, var and let declarations of variables often result in vastly different results.
// var is the function scope, so all I are always the same variable
for (var i = 0; i < 5; ++i) {
setTimeout(() = > console.log(i), 0)}// 5, 5, 5, 5, 5, 5
// let is a block scope. Each iteration loop declares a new iteration variable
for (let i = 0; i < 5; ++i) {
setTimeout(() = > console.log(i), 0)}// 0, 1, 2, 3, 4
Copy the code
3.3.3 const statement
Const and let declarations are basically the same, with the following important differences:
// Variables must be initialized at the same time
const age; // SyntaxError
// The assignment cannot be repeated
const age = 26;
age = 36; // TypeError
Copy the code
The limitation of a const declaration applies only to references to variables to which it refers. If a const variable refers to an object, it may modify properties inside that object.
const person = {};
person.name = 'Matt';
Copy the code
3.3.4 Declaration style and best practices
- Do not use the var
- With let and const, developers should limit themselves to let and const to help improve code quality.
- There is a clear scope
- Position statement
- The value of the constant
- With let and const, developers should limit themselves to let and const to help improve code quality.
- Const takes precedence over let
- Developers should declare variables using const in preference, and only use lets when they know in advance that future changes will be made.
- Let the browser run time force variables to remain unchanged
- Let static code analysis tools detect illegal assignment operations ahead of time
- More quickly detect unexpected behavior due to unexpected assignments
- Developers should declare variables using const in preference, and only use lets when they know in advance that future changes will be made.
3.4 Data Types
Simple data types (also known as primitive types)
- Before the ES6
- Undefined, Null, Number, String, Boolean
- ES6 new
- A Symbol is a Symbol.
- ES10 new
- BigInt
Reference data type: An Object is an unordered collection of name-value pairs.
3.4.1 Typeof operator
Because ECMAScript’s type system is loose, use the Typeof operator to return one of the following strings
- Undefined means the value is undefined
- “Boolean” indicates that the value is Boolean
- “String” indicates that the value is a string
- “Number” indicates that the value is a numerical value
- “Object” indicates that the value is an object or null
- “Function” means the value is a function
- “Symbol” means the value is a symbol
console.log(typeof "abc"); // "string"
console.log(typeof 123); // "number"
Copy the code
- Typeof is an operator, not a function, so no arguments are required.
- Calling Typeof NULL returns “object”, because the special value null is considered a reference to an empty object.
- Strictly speaking, functions are considered objects in ECMAScript, not data types. However, functions also have their own special properties, so it is necessary to use the Typeof operator to distinguish functions from other objects.
3.4.2 Undefined type
Undefined Data types have only one special value: Undefined.
When a variable is declared using var or let but not initialized, it is assigned the value of undefined.
let message; // This variable is declared and assigned to undefined
if (message) {
// This block will not execute
}
if(! message) {// This block will execute
}
if (age) { // Undeclared variables
// There will be an error
}
Copy the code
Rule 3.4.3 Null type
The Null data type has only one special value: Null.
Logically, a null value represents an empty object pointer, which is why passing a NULL to typeof returns “object”. Therefore, when defining variables that will hold object values in the future, it is recommended to use NULL to initialize them.
let cat = null;
console.log(typeof cat); // "object"
Copy the code
- Undefined is derived from null, so console.log(null == undefined); // true
3.4.4 Boolean type
Boolean data types have two literals: true and false (uppercase sensitive).
Values of all other ECMAScript types have the equivalent form of corresponding Boolean values, calling specific Boolean() transition functions or!! Stealth conversion.
The data type | The value converted to true | Convert to a value of false |
---|---|---|
Boolean | true | false |
String | Non-empty string | “” (empty string) |
Number | Nonzero value | 0, NaN |
Object | Any object | null |
Undefined | N/A (not) | undefined |
3.4.5 Number type
The Number type uses IEEE 754 format to represent integers and floating point numbers (also called double values in some languages).
-
Decimal integer: Write it directly
- let intNum = 55;
-
Octal integer: The first digit must be zero (0) + the corresponding octal digit (0 to 7). Otherwise, it will be treated as decimal.
-
let octalNum1 = 070; // octal 56 let octalNum2 = 079; // Invalid octal value, treated as 79 Copy the code
-
-
Hexadecimal integer: prefix 0x (case sensitive) + corresponding hexadecimal digits (0 to 9 and A to F) are case insensitive.
-
let hexNum1 = 0xA; // Hexadecimal 10 let hexNum2 = 0x1f; // Hexadecimal 31 let hexNum3 = 0xg; // Invalid hex, error reported Copy the code
-
Because of the way JavaScript holds numeric values, there may actually be positive zeros (+0) and negative zeros (-0), which are considered equivalent in all cases.
console.log(-0= =0) // true console.log(-0= = =0) // true Copy the code
3.4.5.1 floating point value
Defines a floating point value that must contain a decimal point.
-
let floatNum1 = 0.1; let floatNum2 = 1.; // Valid, but not recommended Copy the code
Since storing floating-point values takes twice as much memory as storing integer values, ECMAScript always tries to convert them to integers:
-
let floatNum1 = 1.; // Handle the integer 1 let floatNum2 = 10.0; // Handle the integer 10 Copy the code
Floating-point numbers can have exact values up to 17 decimal places, but they tend to cause minor rounding errors in arithmetic calculations due to machine code floating-point operations.
For example, 0.1 + 0.2 does not get 0.3, but 0.300 000 000 000 000 04. Do not test for a particular floating point value
3.4.5.2 Range of values
-
The smallest Number ECMAScript can represent: number. MIN_VALUE is 5E-324.
-
MAX_VALUE is 1.797 693 134 862 315 7E +308.
-
If a calculation goes beyond what JavaScript can represent, it is automatically converted to the special Infinity and -infinity values, which cannot be used for any further calculations.
-
To determine if a value isFinite(in the range that JavaScript can represent), use the isFinite() function
-
let InfinityNum = Number.MAX_VALUE + Number.MAX_VALUE; console.log(isFinite(InfinityNum)); // If the argument is NaN, positive or negative infinity will return false, otherwise true. Copy the code
-
3.4.5.3 NaN
NaN: Not a Number, used to indicate that the operation intended to return a Number failed (rather than throwing an error) as in
-
Dividing 0, +0, or -0 returns NaN
-
console.log(0/0); // NaN console.log(-0/+0); // NaN Copy the code
-
-
Returns infinity if the numerator is non-zero and the denominator is 0 or -0
-
console.log(5/0); // Infinity console.log(5/-0); // -Infinity Copy the code
-
NaN is not equal to any value including NaN
console.log(NaN= =NaN) // false
console.log(NaN= = =NaN) // false
The isNaN() function can be used to receive an argument of any type, which is implicitly converted to return a Boolean value.
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false, 10 is a number
console.log(isNaN("10")); // false, which can be converted to the value 10
console.log(isNaN(true)); // false, which can be converted to the value 1
console.log(isNaN("blue")); // true, cannot be converted to a numeric value
Copy the code
3.4.5.4 Numerical Conversion
Number(), parseInt(), and parseFloat(), which can convert non-numeric values to numeric values.
-
The Number() function performs the conversion based on the following rules.
-
Boolean values that convert true to 1 and false to 0.
-
Value, return directly.
-
Null returns 0.
-
Undefined, return NaN.
-
String, apply the following rules.
-
A string is a numeric character (including + and – prefixes) converted to a decimal value.
-
Number("1"); / / 1 Number("0123"); / / 123 Copy the code
-
-
A string containing a valid floating-point value format is converted to the corresponding floating-point value.
-
Number("0.1"); / / 0.1 Number("00.123"); / / 0.123 Copy the code
-
-
A string containing a valid hexadecimal value is converted to a decimal integer value corresponding to that hexadecimal value.
-
Number("0xf"); / / 15 Copy the code
-
-
If the string is empty, 0 is returned.
-
A string that contains characters other than the above returns NaN.
-
-
Object that calls the valueof() method and converts the returned value according to the rules above. If the conversion results in a NaN, the toString() method is called and converted according to the conversion string rules.
-
The unary addition operator follows the same conversion rules as the Number() function.
-
-
The parseInt() function is preferred when an integer is needed. The first argument takes a string, and the second argument takes the specified base (base).
-
Spaces before the string are ignored, and the conversion begins with the first non-space character.
-
The first non-space character in the string that is not a numeric character, plus or minus, will immediately return NaN.
-
If the first non-space character in the string is a numeric character, plus or minus, each character continues to be checked until the end of the string, or a non-numeric character is encountered.
-
If a string is a numeric value in a different base format, it can also be interpreted as an integer in the corresponding base format.
-
let num1 = parseInt("123"); / / 123 let num2 = parseInt("1234blue"); / / 1234 let num3 = parseInt(""); // NaN let num4 = parseInt("0xA"); // 10, interpreted as a hexadecimal integer let num5 = parseInt("22.5"); / / 22 let num6 = parseInt("70"); / / 70 Copy the code
-
With the second parameter, you can greatly expand the type of results obtained after the transformation
-
let num1 = parseInt("AF".16); / / 175 let num2 = parseInt("AF"); // NaN, prefix cannot be omitted if base is not specified. let num3 = parseInt("10".2); // 2. let num4 = parseInt("10".8); // 8. let num5 = parseInt("10".10); // 10, which is resolved in decimal by default. let num6 = parseInt("10".16); // 16 is resolved in hexadecimal format. Copy the code
-
-
-
The parseFloat() function is similar to the parseInt() function above. The main differences are as follows
-
The decimal point can be parsed, but only the first occurrence of the decimal point is valid.
-
Only decimal values are parsed, so base cannot be specified.
-
If the string value is an integer, JavaScript automatically converts it to an integer to save space.
-
let num1 = parseFloat("1.23"); / / 1.23 let num2 = parseFloat("01.234 blue"); / / 1.234 let num3 = parseFloat(""); // NaN let num4 = parseFloat("0xA"); // 0, cannot parse base number. let num5 = parseFloat("22.34.5"); // 22.34, the second decimal point is treated as a normal character. let num6 = parseFloat("3.125 e7"); / / 31250000 Copy the code
-
3.4.6 type String
The String data type represents a sequence of zero or more 16-bit Unicode characters. Strings can be expressed in one of the following formats:
let str1 = "Lindada";
let str2 = 'Lindada';
let str3 = `Lindada`;
Copy the code
ECMAScript syntax for the three forms of strings interprets strings differently than some languages, rendering the same result.
3.4.6.1 Character literals
The string data type contains character literals that represent non-print characters or characters for other purposes, as follows:
literal | meaning |
---|---|
\n | A newline |
\t | TAB |
\b | backspace |
\r | enter |
\f | Change the page |
\ \ | Backslash (\) |
\ ‘ | Single quotes (‘) |
\” | Double quotation marks (“) |
\ ` | Back quotes (‘) |
\xnn | A hexadecimal character denoted by nn (where n is the hexadecimal number 0 to F), for example \x4 equals “A” |
\unnnn | Unicode characters in hexadecimal encoding NNNN, such as \ U03A3 equals the Greek character “sigma” |
The length of a string can be obtained from its length attribute, but if the string contains double-byte characters, the value returned by the length attribute may not be the exact number of characters, as discussed in Chapter 5.
3.4.6.2 Character String Characteristics
Strings in ECMAScript are immutable, meaning that values cannot be changed once created. To change a string value in a variable, you must first destroy the original string and then save another string containing the new value to the variable.
let lang = "Java";
lang += "Script";
/** * The lang variable started as a" Java" string, and was later modified to define a" JavaScript" string. * This means that the entire modification process will first allocate a space large enough to hold 10 characters, fill in "Java" and "Script", and finally destroy the original strings "Java" and "Script". * All processing is done in the background. * /
Copy the code
3.4.6.3 Converting to a String
There are two ways to convert a value to a String, the toString() method and the String conversion function.
-
ToString () : Returns the string equivalent of the current value.
-
let age = 11; let age2Str = age.toString(); / / "11" let found = true; let found2Str = found.toString(); // "true" Copy the code
- Almost all data types have toString() methods, except for null and undefined values.
-
Normally this method takes no arguments, but when it is called on numeric data, it can be converted by passing in the base (base).
-
let num = 10; num.toString(); 10 "/ /" num.toString(2); / / "1010" num.toString(8); / / "12" num.toString(10); // "10", defaults to base 10. num.toString(16); // "a" Copy the code
-
-
-
String() : The String() function can be used when it is uncertain whether a value has a toString() method (null or undefined).
-
The function follows the following rules:
- If the value has a toString() method, the method is called directly (with no arguments) and the result is returned.
- If the value is null, return “null”.
- Return “undefined” if the value is undefined.
-
Here’s an example:
-
String(10); 10 "/ /" String(true); // "true" String(null); // "null" String(undefined); // "undefined" Copy the code
-
-
A value can also be converted to a string by adding “” to it (an empty string) with the plus operator.
3.4.6.4 Template literals
ECMAScript 6 adds the ability for template literals to define strings, keeping newline characters, and defining strings across lines:
// The result is consistent
let multiLineStr = 'first line\nsecond line';
let multiLineTemplateLiteral = `first line
second line`;
// frist line
// second line
multiLineStr === multiLineTemplateLiteral; // true
Copy the code
Template literals are especially useful when defining templates, such as the following HTML template:
let pageHTML = `
Copy the code
Because template literals retain Spaces inside backquotes, well-formed template strings should not have indentation.
let multiLineTemplateLiteral = `first line second line`;
console.log(multiLineTemplateLiteral.length); / / 38
Copy the code
3.4.6.5 String Interpolation
Technically, a template literal is not a string, but a special JavaScript syntactic expression. Immediately evaluated and converted to a string instance upon definition, any inserted variables are also evaluated from their nearest scope.
-
String interpolation is implemented by using a JavaScript expression in ${} :
-
let value = 5; let str = 'second'; // Previously, string interpolation was implemented. let interpolatedStr = value + ' to the ' + str + 'power is ' + (value * value); // 5 to the second power is 25 // Now, use template literals let interpolatedTemplateLiteral = `${value} to the ${str} power is ${value * value}`; // 5 to the second power is 25 Copy the code
-
-
All inserted values are cast to strings using toString().
-
Functions and methods can be called in interpolation expressions:
-
function capitalize(word) { return `${word[0].toUpperCase()} ${word.slice(1)}`; } console.log(`${capitalize('hello')}.${capitalize('world')}! `); // Hello, World! Copy the code
-
3.4.6.6 Template literal label functions
Template literals support defining tag functions that take the template separated by interpolation tokens and evaluate each expression:
let a = 6;
let b = 9;
function simpleTag(strings, aVal, bVal, sumVal) {
console.log(strings);
console.log(aVal);
console.log(bVal);
console.log(sumVal);
return 'value';
}
let untaggedRes = `${a} + ${b} = ${a + b}`;
let taggedRes = simpleTag`${a} + ${b} = ${a + b}`;
// ["", "+ "," = ", "]
/ / 6
/ / 9
/ / 15
console.log(untaggedRes); // "6 + 9 = 15"
console.log(taggedRes); // "value"
Copy the code
If you are not sure of the arguments in the label function, you can use the remaining operators (…). :
let a = 6;
let b = 9;
function simpleTag(strings, ... expressions) {
console.log(strings[0])
return strings[0] +
expressions.map((v, i) = > {
console.log(`${v}${strings[i + 1]}`)
return `${v}${strings[i + 1]}`})
.join(' ');
}
let untaggedRes = `${a} + ${b} = ${a + b}`;
let taggedRes = simpleTag`${a} + ${b} = ${a + b}`;
/ / ""
6 + "/ /"
9 = "/ /"
15 "/ /"
console.log(untaggedRes); // "6 + 9 = 15"
console.log(taggedRes); // "6 + 9 = 15"
Copy the code
3.4.6.7 The Original Character String
Using template literals also allows you to retrieve the original template literal content (such as newlines or Unicode characters) directly, rather than the converted character representation. To do this, you can use the default string. raw tag function:
/ / Unicode example
console.log(`\u00A9`); / / ©
console.log(String.raw`\u00A9`); // \u00A9
// The newline example
console.log(`first line\nsecond line`);
// first line
// second line
console.log(String.raw`first line\nsecond line`); // "first line\nsecond line"
Copy the code
We can also get the raw content of each string using the.raw property of the string array as the first argument to the label function:
function printRaw(strings) {
console.log('Actual characters:');
for (const string of strings) {
console.log(string);
}
console.log('Escaped characters:');
for (const rawString of strings.raw) {
console.log(rawString);
}
}
printRaw`\u00A9The ${'and'}\n`;
// Actual characters:
/ / ©
// (newline)
// Escaped characters:
// \u00A9
// \n
Copy the code
3.4.7 Symbol type
Symbol is a new data type in ECMAScript 6. Symbols are primitive values, and instances of symbols are unique and immutable. The purpose of the symbol is to ensure that an object property has a unique identifier and is then used as a non-string object property without the risk of property collisions.
3.4.7.1 Basic usage of symbols
Symbols need to be initialized using the Symbol() function, which passes a description of the Symbol as a string argument. You can debug the code with this description, but the description has nothing to do with the Symbol definition or identity:
/ / define the Symbol
let sym = Symbol(a);console.log(typeof sym); // symbol
let sym1 = Symbol(a);let sym2 = Symbol(a);console.log(sym1 === sym2); // false
let sym3 = Symbol('foo');
let sym4 = Symbol('foo');
console.log(sym3 === sym4); // false
Copy the code
The Symbol() function cannot be used as a constructor, and is used with the new keyword to avoid creating Symbol wrapped objects.
let mySymbol = new Symbol(a);// TypeError: Symbol is not a constructor
// If you really need symbols to wrap objects, you can use the Object() function
let mySymbol = Symbol(a);let myWrappedSymbol = Object(mySymbol);
console.log(typeof myWrappedSymbol); // "object"
Copy the code
3.4.7.2 Using the Global Symbol Registry
-
Symbol.for() method: Different parts of the runtime need to share and reuse instances of symbols, so you can use a Symbol string as a key.
-
let globalSymbol = Symbol.for('foo'); // Subsequent calls using the same string will check the registry, but will check for instances of the symbol let otherGlobalSymbol = Symbol.for('foo'); // Symbols defined in the global registry are not the same as those defined using Symbol(), even with the same Symbol description let localSymbol = Symbol('foo'); console.log(typeof fooGlobalSymbol); // symbol console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true console.log(fooGlobalSymbol === localSymbol); // false Copy the code
-
-
Symbols in the global registry must be created using string keys, so any value passed in symbol.for () is converted to a string.
-
You can also query the global registry using symbol.keyfor ()
-
// Create a global symbol let s = Symbol.for('foo'); console.log(Symbol.keyFor(s)); // foo // Create a normal symbol, not a global symbol returns undefined let s2 = Symbol('foo'); console.log(Symbol.keyFor(s2)); // undefined // If no symbol is passed in, TypeError is raised Symbol.keyFor(123); // TypeError: 123 is not a symbol Copy the code
-
3.4.7.3 Using symbols as attributes
-
Wherever you can use strings or values as attributes, you can use symbols instead. Includes Object literal properties and properties defined by Object.defineProperty()/Object.definedProperties(). Object literals can only use symbols as attributes in the computed attribute syntax.
-
let s1 = Symbol('foo'), s2 = Symbol('bar'); let o = { [s1]: 'foo val' }; let o[s1] = 'foo val'; Object.defineProperty(o, s1, {value: 'foo val'}); Object.defineProperties(o, { [s1]: {value: 'foo value'}, [s2]: {value: 'bar value'}})Copy the code
-
-
Returns the property method of an object instance
-
let s1 = Symbol('foo'), s2 = Symbol('bar'); let o = { [s1]: 'foo val', [s2]: 'bar val'.baz: 'baz val'.qux: 'qux val' }; Object.getOwnPropertySymbols(o); // [Symbol(foo), Symbol(bar)] Object.getOwnPropertyNames(o); // ["bar", "qux"] Object.getOwnPropertyDescriptors(o); // {baz: {... }, qux: {... }, Symbol(foo): {... }, Symbol(bar): {... }} Reflect.ownKeys(o); // ["baz", "qux", Symbol(foo), Symbol(bar)] Copy the code
-
3.4.7.4 Common Built-in Symbols
ECMAScript 6 introduces a set of commonly used built-in notations to expose language internal behavior that developers can access, rewrite, or emulate worldwide. The built-in Symbol is the plain string property of the global function Symbol that points to an instance of a Symbol.
References to the ECMAScript specification refer to the names of symbols in the specification, prefixed with @@. For example, @@iterator is symbol. iterator.
-
Symbol.hasinstance: a method that determines whether a constructor object recognizes an object as an instance of it. Used by the instanceof operator.
-
In ES6, the instanceof operator uses the symbol.hasinstance function to determine the relationship
-
function Foo() {} let f = new Foo(); // It works the same way console.log(f instanceof Foo); // true console.log(Foo[Symbol.hasInstance](f)); // true Copy the code
-
-
This function can be redefined statically on an inherited class.
-
class F {} class C extends F { static [Symbol.hasInstance]() { return false; }}let c = new C(); // Default behavior console.log(c instanceof F); // true console.log(F[Symbol.hasInstance](c)); // true // Customize behavior by overriding the built-in symbols console.log(c instanceof C); // false console.log(C[Symbol.hasInstance](c)); // false Copy the code
-
-
-
Symbol. IsConcatSpreadable: a Boolean value, if it is true, means that the object should be used Array. The prototype. The concat () draw the Array elements.
-
The array.prototype.concat () method in ES6 selects how to concatenate an array-like object into an Array instance based on the type of object it receives. The following coverage Symbol. IsConcatSpreadable values can modify this behavior:
- The array object
- By default, it is flattened to an existing array.
- False or false values cause the entire object to be appended to the end of the array.
- Array like object
- The default is appended to the end of the array.
- A true or true value causes the array-like object to be flattened to the array instance.
- Any other object that is not an array-like object
- True or true values are ignored.
- The array object
-
The code demonstrates the above:
-
// Array object let initial = ['foo']; let array = ['bar']; console.log(array[Symbol.isConcatSpreadable]); // undefined console.log(initial.concat(array)); // ['foo', 'bar'] array.[Symbol.isConcatSpreadable] = false; // Change the built-in symbol console.log(initial.concat(array)); // ['foo', Array(1)] Copy the code
-
// Class array object let initial = ['foo']; let arrayLikeObject = { length: 1.0: 'baz' }; console.log(arrayLikeObject[Symbol.isConcatSpreadable]); // undefined console.log(initial.concat(arrayLikeObject)); // ['foo', {...}] arrayLikeObject.[Symbol.isConcatSpreadable] = true; // Change the built-in symbol console.log(initial.concat(arrayLikeObject)); // ['foo', 'baz'] Copy the code
-
// Class array object let initial = ['foo']; let otherObject = new Set().add('qux') console.log(otherObject[Symbol.isConcatSpreadable]); // undefined console.log(initial.concat(otherObject)); // ['foo', Set(1)] otherObject.[Symbol.isConcatSpreadable] = true; // Change the built-in symbol console.log(initial.concat(otherObject)); // ['foo'] Copy the code
-
-
[].concat() by default flattens the array and concatenates it to the end. You can use built-in symbols for special purposes.
-
-
Symbol.asyncIterator: a method that returns the object’s default asyncIterator. Used by the for-await-of statement.
-
This object generated by the symbol. asyncIterator function can be returned implicitly by the asynchronous generator function:
-
class Emitter { constructor(max) { this.max = max; this.asyncIdx = 0; } // Implicitly modify the default behavior of for-await-of with symbols async* [Symbol.asyncIterator](){ while(this.asyncIdx < this.max) { yield new Promise((resolve) = > resolve(this.asyncIdx++)); }}}async function asyncCount() { let emitter = new Emitter(5); for await(const x of emitter) { console.log(x); } } asyncCount(); / / 0 / / 1 / / 2 / / 3 / / 4 Copy the code
-
-
-
Symbol.iterator: a method that returns the default iterator for an object. Used by for-of statements
-
This object generated by the symbol. iterator function can be returned implicitly by the generator function:
-
class Emitter { constructor(max) { this.max = max; this.Idx = 0; } // Implicitly modify the default behavior of for-await-of with symbols async* [Symbol.iterator](){ while(this.Idx < this.max) { yield this.Idx++; }}}function count() { let emitter = new Emitter(5); for (const x of emitter) { console.log(x); } } count(); / / 0 / / 1 / / 2 / / 3 / / 4 Copy the code
-
The rest of the iterator is covered in more detail in Chapter 7.
-
-
-
Symbol.match: A regular expression method that uses regular expressions to match strings. Used by the prototype.match() method.
-
The string.prototype.match () method evaluates regular expressions using functions with symbol.match as keys.
-
The symbol.match function takes one argument, which is an instance of the string that calls the match() method. There is no limit to the value returned:
-
class FooMatcher { static [Symbol.match](target) { return target.includes('foo'); }}console.log('foobar'.match(FooMatcher)); // true console.log('barbaz'.match(FooMatcher)); // false class StringMatcher { constructor(str) { this.str = str } [Symbol.match](target) { // Reset the string.prototype.match () method return target.includes(this.str); }}console.log('foobar'.match(new StringMatcher('foo'))); // true console.log('barbaz'.match(new StringMatcher('qux'))); // false Copy the code
-
-
-
Symbol.replace: A regular expression method that replaces matched substrings in a string. Used by the string.prototype.replace () method.
-
The string.prototype.replace () method evaluates regular expressions using functions with symbol.replace as keys.
-
The symbol.replace function takes two arguments, calling the replace() method string instance and the replacement string. There is no limit to the value returned:
-
class FooReplacer { static [Symbol.replace](target, replacement) { return target.split('foo').join(replacement); }}console.log('barfoobaz'.replace(FooReplacer, 'qux')); // "barquxbaz" class StringReplacer { constructor(str) { this.str = str; } [Symbol.replace](target, replacement) { return target.split(this.str).join(replacement); }}console.log('barfoobaz'.replace(new StringReplacer('foo'), 'qux')); // "barquxbaz" Copy the code
-
-
-
Symbol.search: A regular expression method that returns the index in a string that matches the regular expression. Used by the string.prototype.search () method.
-
The string.prototype.search () method evaluates regular expressions using functions with symbol.search as keys.
-
The symbol.search function takes an argument that is an instance of the string that calls the match() method. There is no limit to the value returned:
-
class FooSearcher { static [Symbol.search](target) { return target.indexOf('foo'); }}console.log('foobar'.replace(FooSearcher)); / / 0 console.log('barfoo'.replace(FooSearcher)); / / 3 console.log('barbaz'.replace(FooSearcher)); // -1 class StringSearcher { constructor(str) { this.str = str; } [Symbol.search](target) { return target.indexOf(this.str); }}console.log('foobar'.replace(new FooSearcher('foo'))); / / 0 console.log('barfoo'.replace(new FooSearcher('foo'))); / / 3 console.log('barbaz'.replace(new FooSearcher('qux'))); // -1 Copy the code
-
-
-
Symbol.species: Value of a function used as a constructor to create a derived object.
-
This property is most commonly used in built-in types, using symbol.species to define static getter methods that override the stereotype definition of newly created instances:
-
class Bar extends Array {} class Baz extends Array { static get [Symbol.species]() { return Array; }}let bar = new Bar(); console.log(bar instanceof Array); // true console.log(bar instanceof Bar); // true bar = bar.concat('bar'); console.log(bar); // Bar(1) [ 'bar' ] console.log(bar instanceof Array); // true console.log(bar instanceof Bar); // true let baz = new Baz(); console.log(baz instanceof Array); // true console.log(baz instanceof Baz); // true baz = baz.concat('baz'); console.log(baz); // [ 'bar' ] console.log(baz instanceof Array); // true // symbol.species Built-in reset console.log(baz instanceof Baz); // false Copy the code
-
-
-
Symbol.split: A regular expression method that splits a string at the index position that matches the regular expression. Used by the string.prototype.split () method.
-
The string.prototype.split () method uses functions with symbol.split as keys to evaluate regular expressions.
-
The symbol.split function takes one argument, which is an instance of the string that calls the match() method. There is no limit to the value returned:
-
class FooSplitter { static [Symbol.split](target) { return target.split('foo'); }}console.log('barfoobaz'.split(FooSplitter)); // ["bar", "baz"] class StringSplitter{ constructor(str) { this.str = str; } [Symbol.split](target) { return target.split(this.str); }}console.log('barfoobaz'.split(new StringSplitter('foo'))); // ["bar", "baz"] Copy the code
-
-
-
Symbol.toPrimitive: A method that converts an object to its corresponding original value, used by the toPrimitive abstraction operation.
-
Depending on the argument supplied to the function (string, number, or default), you can control the raw value returned:
-
class Foo {} class Bar { constructor() { this[Symbol.toPrimitive] = function(hint) { switch (hint) { case 'number': return 3; case 'string': return 'string bar'; case 'default': default: return 'default bar'; }}}}let foo = new Foo(); console.log(3 + foo); // "3[object Object]" console.log(3 - foo); // NaN console.log(String(foo)); // "[object Object]" let bar = new Bar(); console.log(3 + bar); // "3default bar" console.log(3 - bar); / / 0 console.log(String(bar)); // "string bar" console.log(Number(bar)); / / 3 Copy the code
-
-
-
Symbol.tostringtag: A string used to create the default string description of an object. By the method of built-in Object. The prototype. The toString () is used.
-
let s = new Set(a);class Foo {} let foo = new Foo(); class Bar { constructor() { this[Symbol.toStringTag] = 'Bar'; }}let bar = new Bar(); console.log(s.toString()); // [object Set] console.log(s[Symbol.toStringTag]); // Set console.log(foo.toString()); // [object Object] console.log(foo[Symbol.toStringTag]); // Object console.log(bar.toString()); // [object Bar] console.log(bar[Symbol.toStringTag]); // Bar Copy the code
-
3.4.8 Object type
An object in ECMAScript is simply a collection of data and functionality.
let o = new Object(a);let o2 = new Object; // Legal, but not recommended
Copy the code
Object is the base class for deriving other objects. All attributes and methods of Object type also exist on the derived objects. Each Object instance has the following attributes and methods.
- Constructor: The function used to create the current object.
- HasOwnProperty () : Determines whether a given property exists on the current object instance (not the prototype). Pass in the string argument.
- IsPrototypeof () : Used to determine whether the current object is a prototype of another object. Pass in the string argument.
- PropertyIsEnumerable () : Used to determine if a given property can be enumerated in a for-in statement. Pass in the string argument.
- ToLocaleString () : Returns a string representation of an object that reflects its localized execution environment.
- ToString () : Returns a string representation of an object.
- ValueOf () : Returns a string, value, or Boolean representation of an object. Usually the same as the return value of toString().
Strictly speaking, BOM and DOM objects in the browser environment are host objects defined and provided by the host environment. Host objects are not bound by ECMA-262, so they may or may not inherit Object.
3.5 the operator
Ecma-262 describes a set of operators that can be used to manipulate data values, including mathematical operators (such as addition and subtraction), bitwise operators, relational operators, and equality operators. When applied to an object, the operator usually calls the valueof() or toString() methods to get a value that can be computed
3.5.1 Unary operators
-
The increment/decrement operator is directly copied from C and can operate on any value, integer, string, Boolean, floating point, or even object. The increment and decrement operators follow the following rules:
-
string
- A valid numerical form, converted to a numerical value and then applied to the change. The variable type changes from a string to a number.
- Invalid numeric form, set variable value to NaN. The variable type changes from a string to a number.
-
Boolean value
- False, convert to 0 before applying the change. The variable type changes from a Boolean to a numeric value.
- True, convert to 1 before applying the change. The variable type changes from a Boolean to a numeric value.
-
Floating-point value: add or subtract 1 directly.
-
Object: Call its valueof() method to get an operable value, and apply the above rules to the resulting value. In the case of NaN, toString() is called and the other rules are applied again. The variable type changes from object to value.
-
// demonstrate the above rules let s1 = "2"; let s2 = "z"; let b = false; let f = 1.1; let o = { valueof() { return -1; } } s1++; // The value becomes the number 3 s2++; // The value becomes NaN b++; // The value becomes 1 f--; // The value becomes 0.10000000000000009 (because the floating point number is imprecise) o--; // The value becomes -2 Copy the code
-
-
Unary plus and minus: They are used in ECMAScript as in high school math for data type conversions.
-
Unary addition is indicated by a plus sign (+) that precedes the variable and has no effect on the value.
-
// demonstrate the above rules let s1 = "01"; let s2 = "1.1"; let s3 = "z"; let b = false; let f = 1.1; let o = { valueof() { return -1; } } s1 = +s1; // The value becomes 1 s2 = +s2; // The value becomes 1.1 s3 = +s3; // The value becomes NaN b = +b; // The value becomes 0 f = +f; // The value becomes 1.1 o = +o; // The value becomes -1 Copy the code
-
-
Unary subtraction is indicated by a minus sign (-), which is placed at the head of the variable to make it the corresponding negative value
-
// demonstrate the above rules let s1 = "01"; let s2 = "1.1"; let s3 = "z"; let b = false; let f = 1.1; let o = { valueof() { return -1; } } s1 = -s1; // The value becomes the value -1 s2 = -s2; // The value becomes -1.1 s3 = -s3; // The value becomes NaN b = -b; // The value becomes 0 f = -f; // The value becomes -1.1 o = -o; // The value becomes 1 Copy the code
-
-
3.5.2 bit operators
All values in ECMAScript are stored in 64-bit format, but bitwise operations do not apply directly to 64-bit representations. Instead, values are converted to 32-bit integers, then bitwise operations are performed, and then the result is converted to 64-bit. Therefore, only 32-bit integers need to be considered when performing bitwise operators.
-
The first 31 bits of a signed integer represent an integer value, and the 32nd bit represents the sign of the value. 0 is positive, 1 is negative.
-
Unsigned integers have a larger range than signed integers because all 32 bits represent integer values.
By default, all integers in ECMAScript are represented as signed numbers.
3.5.2.1 bitwise not
Represented by ~, which returns the inverse of the binary of a numeric value and is one of the binary mathematical operators.
let num1 = 25; // Binary 00000000 00000000 00000000 00011001
let num2 = ~num1; // Binary 11111111 11111111 11111111 11100110
console.log(num2); / / - 26
// Bitwise not, that is, the binary value of the inverse.
// The final effect is to reverse the decimal number and subtract 1, as follows.
let num3 = 25;
let num4 = -num3 - 1;
console.log(num4); / / 26
Copy the code
Although both return the same result, the bitwise operator is much faster. This is because bitwise operations are done on the underlying representation of the value.
3.5.2.2 bitwise and
Represented by &, there are two operands, return 1 if each of the two operands corresponds to the same bit, otherwise return 0.
let result = 25 & 3; / / 1
/** * 25 = 0000 0000 0000 0000 0000 0000 0001 1001 * 3 = 0000 0000 0000 0000 0000 0000 0000 0011 * AND = 0000 0000 0000 0000 0000 0000 0000 0001 */
let result2 = 25 & 20; / / 16
/** * 25 = 0000 0000 0000 0000 0000 0000 0001 1001 * 20 = 0000 0000 0000 0000 0000 0000 0001 0100 * AND = 0000 0000 0000 0000 0000 0000 0000 0000 0000 */
Copy the code
3.5.2.3 bitwise or
Use | said, there are two operators, return two operands binary each corresponding to a same returns 1, otherwise it returns 0.
let result = 25 & 3; / / 27
/** * 25 = 0000 0000 0000 0000 0000 0000 0001 1001 * 3 = 0000 0000 0000 0000 0000 0000 0000 0011 * AND = 0000 0000 0000 0000 0000 0000 0001 1011 */
Copy the code
3.5.2.4 Bitwise XOR
The two operators, represented by ^, return two operands, one for each of the same bits, and zero otherwise.
let result = 25 & 3; / / 26
/** * 25 = 0000 0000 0000 0000 0000 0000 0001 1001 * 3 = 0000 0000 0000 0000 0000 0000 0000 0011 * AND = 0000 0000 0000 0000 0000 0000 0001 1010 */
Copy the code
3.5.2.5 left
Represented by <<, all the bits of a numeric value are moved to the left by the specified number of bits, filling the space with 0 (reserving the leftmost sign bit of the 32 bits).
let oldValue = 2; // Binary 10
let newValue = oldValue << 5; // Binary 1000000 => 64
// The left shift preserves the sign bit
let oldValue2 = -2; // binary -10
let newValue2 = oldValue2 << 5; // Binary -1000000 => -64
Copy the code
3.5.2.6 Symbols move to the right
Represented by >>, moves all bits of a numeric value to the right by the specified number of bits, while preserving the sign (positive or negative), (preserving the leftmost sign bit of the 32 bits).
let oldValue = 64; // Binary 1000000
let newValue = oldValue >> 5; // Binary 10 => 2
// The left shift preserves the sign bit
let oldValue2 = -64; // Binary -1000000
let newValue2 = oldValue2 >> 5; // Binary -10 => -2
Copy the code
3.5.2.7 Unsigned right shift
Represented by >>>, all the bits of a value are moved to the right according to the specified number of bits, without retaining the symbol, and the range of representations becomes larger.
-
Positive: An unsigned right shift results in the same result as a signed right shift.
-
let oldValue = 64; // Binary 1000000 let newValue = oldValue >> 5; // Binary 10 => 2 Copy the code
-
-
Negative numbers: An unsigned right shift adds 0 to the empty space (no sign bits are reserved), so the result becomes very large.
-
let oldValue = -64; // binary 11111111 11111111 11111111 11000000, the unsigned negative number is the double complement of its absolute value. let newValue = oldValue >>> 5; // Binary 00000111 11111111 11111111 11111110, decimal 134217726 Copy the code
-
3.5.3 Boolean operators
There are three Boolean operators: logical not, logical and logical or.
-
! Logical non: This operator first converts the operand to a Boolean value and then inverts it.
- Object, returns false.
- An empty string returns true.
- If the string is not empty, false is returned.
- The value 0 returns true.
- Non-zero values (including Infinity) return false.
- Null returns true.
- NaN, returns true.
- Undefined returns true.
console.log(!false); // true console.log(!"blue"); // false console.log(!0); // true console.log(!NaN); // true console.log(!""); // true console.log(!12345); // false Copy the code
Use two logical non at the same time!! Equivalent to calling the transformation function Boolean().
-
The && and: operator applies to two values and follows the following rules:
-
The first operand Second operand The results of true true true true false false false true false false false false When the first operator is true, the second operator is applied. The reverse does not apply to the second operator and can therefore be used as a short-circuit operator.
let found = true; let result = (found && undeclaredVariable); // Apply to undefined undeclaredVariable console.log(result); // This line will not be executed let found2 = false; let result2 = (found2 && undeclaredVariable); // Does not apply to undefined undeclaredvariables. console.log(result2); // Will execute this line, printing false. Copy the code
-
-
| | logic or that the operator is applied to two values, and follow the following rules:
-
The first operand Second operand The results of true true true true false true false true true false false false Like logic, logic may also have the property of segments. When the first operand evaluates to true, the second operand is not evaluated.
let found = false; let result = (found || undeclaredVariable); // Apply to undefined undeclaredVariable console.log(result); // This line will not be executed let found2 = true; let result2 = (found2 && undeclaredVariable); // Does not apply to undefined undeclaredvariables. console.log(result2); // Will execute this line, printing false. // Using this behavior, you can avoid assigning a variable to null or undefined. let myObject = preferredObject || backupObject // backupObject can be seen as an alternate value. Copy the code
-
3.5.6 Additive operators
Additive operators, the addition and subtraction operators, convert different data types behind the scenes in ECMAScript.
-
The + addition operator is used to find the sum of two numbers and apply the following conversion rules:
- Both operands are numeric
- NaN is returned if any operand is NaN.
- Infinity plus Infinity returns Infinity.
- -infinity plus -infinity returns -infinity.
- Infinity plus -infinity returns NaN.
- -0 plus +0 returns +0.
- The two operands are not necessarily numeric
- If both are strings, concatenate the second string to the end of the first string.
- If any operand is a string, the other operand is converted to a string and concatenated.
- If any of the operands are of other data types, their toString() method is called and then concatenated.
// Common error: string and num1 add to a string, num2 add to a string. let num1 = 5; let num2 = 10; let message = "The sum of 5 and 10 is " + num1 + num2; console.log(message); // "The sum of 5 and 10 is 510" // Resolve: add values first, then concatenate them into strings. let num1 = 5; let num2 = 10; let message = "The sum of 5 and 10 is " + (num1 + num2); console.log(message); // "The sum of 5 and 10 is 15" Copy the code
- Both operands are numeric
-
– The subtraction operator, used to find the difference between two numbers and apply the following conversion rules:
-
Both operands are numeric
- NaN is returned if any operand is NaN.
- Infinity minus Infinity returns NaN.
- -infinity minus -infinity returns NaN.
- Infinity minus -infinity returns Infinity.
- +0 minus -0 returns -0.
- -0 minus -0 returns +0.
-
If any operand is a string, Boolean, null, or undefined, it is converted to a value behind the scenes using Number(), and the above rules apply.
-
Any operand is an object
- If there is a valueOf() method, call its valueOf() method to get the value that represents it.
- If there is no valueOf() method, its toString() method is called and the resulting string is then converted to a numeric value.
// demonstrate the above rules let res1 = 5 - true; / / 4 let res2 = NaN - 1; //NaN let res3 = 5 - 3; / / 2 let res4 = 5 - ""; / / 5 let res5 = 5 - "2"; / / 3 let res6 = 5 - null; / / 5 Copy the code
-
3.5.7 Relational operators
The relational operator performs the comparison of two values, including less than (<), greater than (>), less than or equal to (<=), greater than or equal to (>=), and returns a Boolean value. Type conversions and other behaviors occur when applied to different data types as follows:
- If both values are values, a numeric comparison is performed.
- Is a string, the encoding of the corresponding character in the string is compared one by one.
- If either operand is a value, the other operand is converted to a value, performing a numeric comparison.
- If any of the operands is a Boolean value, it is converted to a value before the comparison is performed.
- Any operand is an object
- If there is a valueOf() method, perform the comparison according to the previous rules after the result is obtained.
- If there is no valueOf() method, the toString() method is called and the comparison is performed according to the previous rules.
// Common relational operator errors
// 1. The uppercase letter is smaller than the lowercase letter
let resultError1 = "Brick" < "alphabet"; // true
let resultGreat1 = "Brick".toLowerCase() < "alphabet".toLowerCase(); // false
// 2. Numeric string, inconsistent character encoding.
let resultError2 = "23" < "3"; // true
let resultGreat2 = "23" < 3; // false
// 3. Return false if the relational operator involves a NaN.
let result1 = NaN < 3; // false
let result2 = NaN> =3; // false
Copy the code
3.5.8 Equality operator
ECMAScript provides two sets of operators. The first group is equal and not equal, and the conversion is performed before the comparison. The second group is congruent and incongruent, and the conversion is not performed before the comparison.
3.5.8.1 Equal and not equal
The equal operator is represented by (==); the unequal operator is represented by (! =) represents. Both operators perform a cast before determining whether the operands are equal.
Follow these conversion rules:
- If any of the operands is a Boolean, it is converted to a value and then compared for equality. False converts to 0 and true converts to 1.
- If one operand is a string and the other is a value, the string is converted to a value and then compared for equality.
- If one of the operands is an object and the other is not, valueOf() of the object is called to get the original value, which is then compared according to the previous rules.
Follow the following comparison rules:
- Null is equal to undefined.
- Null and undefined cannot be converted to other types of values for comparison.
- All operands are unequal if they are NaN. By rule, NaN does not equal NaN.
- If both operators are objects, they are the same object. If they are, they are equal. If they are not, they are not equal.
The following table lists some special cases and comparison results
expression | The results of |
---|---|
null == undefined | true |
“NaN” == NaN | false |
5 == NaN | false |
NaN == NaN | false |
NaN ! = NaN | true |
false == 0 | true |
true == 1 | true |
true == 2 | false |
undefined == 0 | false |
null == 0 | false |
“5” = = 5 | true |
3.5.8.2 Congruence and incongruence
Congruent operators are represented by (===) and incongruent operators by (! ==) indicates. Neither operator performs a cast to determine whether the operands are equal.
let res1 = ("55"= =55); // true, equal after conversion.
let res2 = ("55"= = =55); // false, different data type.
let res3 = ("55"! =55); // false, equal after conversion.
let res4 = ("55"! = =55); // true, different data types.
let res5 = (null= =undefined); // true, both values are similar.
let res6 = (null! = =undefined); // false, different data type.
Copy the code
The congruence and incongruence operators are recommended because of type conversion problems with the equality and inequality operators. Helps maintain data type integrity in your code.
3.5.9 Conditional operators
// boolean_expression returns true_value with variable for true and vice versa.
variable = boolean_expression ? true_value : false_value;
Copy the code
3.5.11 Comma operator
The comma operator can be used to perform multiple operations in a single statement.
let num1 = 1, num2 = 2, num3 = 3;
// Assigning multiple values using the comma operator eventually returns the last value in the expression.
let num2 = (5.1.4.8.0); / / 0
Copy the code
3.6 the statement
Ecma-262 describes statements (also known as flow control statements) in which most of the syntax in ECMAScript is expressed.
3.6.2 do – while statement
A do-while statement is a post-test loop that executes code in the loop at least once before exiting.
let i = 0;
do {
i += 2;
console.log(i);
} while (i < 10);
// 2, 4, 6, 8, 10
Copy the code
3.6.5 the for in statement
A for-in statement is a strictly iterative statement that enumerates non-symbolic key attributes in an object. If the iterated variable is null or undefined, the body of the loop is not executed.
const obj = {
name: "lindada".age: 21.job: null
}
for (const propName in obj) { // const ensures that this local variable is not modified.
console.log(propName) // The order of the attributes returned may not be consistent.
}
// Name, age, job
Copy the code
3.6.6 for – statement
A for-of statement is a strict iteration statement that iterates through the elements of an iterable.
for(const el of [2.4.6.8]) {
console.log(el);
}
// 2, 4, 6, 8
Copy the code
The for-of loop iterates over the elements in the order in which the iterable’s next() method produces the values, as discussed in Chapter 7.
ES2018 extends for-of statements by adding for-await-of loops to support asynchronous iterables that generate promises.
3.6.7 Label Statement
Label statements are used to label statements
start: for (let i = 0; i < count; i++) {
console.log(i);
}
// Start is the label of the for statement and can be referenced by a break or continue statement
// Very useful in nested loops.
Copy the code
3.6.8 Break and continue statements
Provides tighter control over the execution of loop code. The break statement is used to immediately break out of the loop and enforce the execution of the next statement after the loop. The continue statement is also used to jump out of the loop immediately, but is executed again from the top of the loop.
// Break and continue with label statements to control statements for external nested loops
let num1 = 0;
outermost1:
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
breakoutermost1; } num1++; }}console.log(num1); / / 55
// When both I and j are 5, break breaks to end the outerMost loop statement.
let num2 = 0;
outermost2:
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
continueoutermost2; } num2++; }}console.log(num2); / / 95
// When both I and j are 5, continue terminates the outerMost loop for the next loop.
Copy the code
3.6.10 switch statement
The switch statement is a flow-control statement closely related to the if statement. The following two statements are equivalent:
const i = 25;
if (i === 25) {
console.log("25");
} else if (i == 35) {
console.log("35");
} else {
console.log("Other");
}
/ / equivalent
switch (i) {
case 25:
console.log("25");
break;
case 35:
console.log("35");
break;
default:
console.log("Other");
}
Copy the code
Each case condition must be followed by a break statement. If several conditions need to be matched in a row, it is recommended to write a comment indicating the condition:
const i = 25;
switch (i) {
case 25:
/ * * /
case 35:
console.log("25 or 35");
default:
conosle.log(Other);
}
Copy the code
ECMAScript gives switch statements unique features that can be used for all data types (not just numerical values). Case conditions are not just constants, they can be variables or expressions.
The switch statement uses the congruent operator when comparing the value of each condition, so it does not cast the data type.
let num = 25;
switch (true) {
case num < 0:
console.log("Less than 0");
break;
case num >= 0 && num <= 10:
console.log("Between 0 and 10");
break;
default:
console.log("More than 20");
}
Copy the code
3.7 the function
Functions in ECMAScript are declared using the function keyword, followed by a set of parameters, followed by the function body. (Chapter 10 covers functions in more detail.)
function sayHi(name, message) {
console.log("Hello" + name + "," + message);
}
// Call a function by its name
sayHi("lindada"."how are you today?"); // "Hello lindada, how are you today?"
Copy the code
- There is no special declaration that the function returns a value other than the return statement, as follows:
function sum(num1, num2) {
return num1 + num2;
}
const result = sum(5.10); / / 15
Copy the code
- Whenever a return statement is encountered, the function immediately stops execution and exits.
function sum2(num1, num2) {
return num1 + num2;
console.log("can't do it!"); // Will not be executed
}
Copy the code
- A return statement can also have no return value. In this case, the function immediately stops execution and returns undefined, which is most commonly used to prematurely terminate the function.
function sayHi(name, message) {
return; // terminate returns undefined
console.log("Hello" + name + "," + message); // Will not be executed
}
Copy the code
Strict mode also has some restrictions on functions, which can result in syntax errors if the following rules are violated:
- Functions cannot have eval or arguments seat names;
- Arguments to functions cannot be called eval or arguments;
- The arguments of two functions cannot have the same name.
3.8 summary
The core language features of JavaScript are defined in ECMA-262 in the form of the pseudo-language ECMAScript. Understanding ECMAScript and its complex details is key to fully understanding JavaScript in a browser. Here’s a summary of the basic elements in ECMAScript.
- Basic data types in ECMAScript
- Before the ES6
- Undefined, Null, Boolean, Number, String
- After ES6 and before ES10
- The new Symbol
- After ES10
- New BigInt
- Before the ES6
- ECMAScript does not distinguish between integers and floating-point numbers; there is only one numeric data type, Number.
- Object is a complex data type that is the base class for all objects in the language.
- Strict patterns impose restrictions on certain error-prone parts of the language.
- ECMAScript provides many of the basic operators common in C and C-like languages.
- Flow control statements are mostly borrowed from other languages.
Function features in ECMAScript
- There is no need to specify the return value of a function, because any function can return any value at any time.
- Functions that do not specify a return value actually return the special value undefined.