1 Statement
1-1 "Three ways of js function declaration:"
(1) Function() constructor
var f =new Function()
(2) Function declaration
function f (){
console.log(2);
}
(3) Function expression
var f = function() {
console.log(1);
}
1-2 "js variable declaration:"
- Variables declared by var will be mounted on the window, while variables declared by let and const will not
- Var declared variables have variable promotion, let and const do not have variable promotion (strictly speaking, let also exists)
- let and const declarations form block scope
- let there is a temporary dead zone
- const declaration must be assigned
(1) Variables declared by var will be mounted on the window, while variables declared by let and const will not:
var a = 100;
console.log(a,window.a); // 100 100
let b = 10;
console.log(b,window.b); // 10 undefined
const c = 1;
console.log(c,window.c); // 1 undefined
(2) Var declared variables have variable promotion, let and const have no variable promotion
console.log(a); // undefined ===> a已声明还没赋值,默认得到undefined值
var a = 100;
console.log(b); // 报错:b is not defined ===> 找不到b这个变量
let b = 10;
console.log(c); // 报错:c is not defined ===> 找不到c这个变量
const c = 10;
(3) let and const declarations form block scope
if(1){
var a = 100;
let b = 10;
}
console.log(a); // 100
console.log(b) // 报错:b is not defined ===> 找不到b这个变量
//
if(1){
var a = 100;
const c = 1;
}
console.log(a); // 100
console.log(c) // 报错:c is not defined ===> 找不到c这个变量
(4) Let and const cannot be declared repeatedly in the same scope, while var can
var a = 100;
console.log(a); // 100
var a = 10;
console.log(a); // 10
let a = 100;
let a = 10;
// 控制台报错:Identifier 'a' has already been declared ===> 标识符a已经被声明了。
(5) Temporary dead zone
var a = 100;
if(1){
a = 10;
let a = 1;
//在当前块作用域中存在a使用let/const声明的情况下,给a赋值10时,只会在当前作用域查找变量a,
// 而这时,还未到声明时候,所以控制台Error:a is not defined
// 即let 和 const 不会声明提前
}
(6) const
一旦声明必须赋值,不能使用null占位。
声明后不能再修改
如果声明的是引用类型数据,可以修改其属性
const a = 100;
const list = [];
list[0] = 10;
console.log(list); // [10]
const obj = {a:100};
obj.name = 'apple';
obj.a = 10000;
console.log(obj); // {a:10000,name:'apple'}
2 Classification of data types:
2-1 Basic types:
- string (string)-primitive type
- boolean (Boolean)-primitive type
- number (number)-primitive type
- symbol-primitive type
- null (empty value)
- undefined
- BigInt (The purpose of the BigInt data type is to have a larger range of integer values than the Number data type, the precision is in the range of (2^53-1), and the value of BigInt(10) is: 10n) New in ES2020
Among them, Symbol
and BigInt
are newly added data types ES6
- Symbol represents a unique and immutable data type after creation. It is mainly used to solve possible global variable conflicts.
- BigInt is a digital type of data, which can represent integers in arbitrary precision format. Using BigInt can safely store and manipulate large integers, even if the number has exceeded the safe integer range that Number can represent.
Note: NaN is not a data type
typeof NaN === 'number' //true
NaN==NaN //false
2-2 Object types (reference types), there are the following 3 types:
A. Built-in objects/Native objects
String、Number、Boolean、Array、Date、RegExp、Math、 Error、 Object、Function、 Global
B. Host object
- (1) BOM objects: Window, Navigator, Screen, History, Location
- (2) DOM objects: Document, Body, Button, Canvas, etc.
C. Custom object-(refers to the object created by the user, compatibility issues need to be noted by the writer)
There are several ways to create custom objects:
(1) Object direct quantity:
var obj1 = {};
var obj2 = {x:0,y:0};
var obj3 = {name:‘Mary’,age:18}
(2) Factory mode-use functions to encapsulate the details of creating objects with specific interfaces:
function createPerson(name,age,job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
return o;
}
var person1 = createPerson('zhang',30,'java');
(3) Constructor mode:
function Person(name,age,job){
this.name= name;
this.age = age;
this.job = job;
}
var person1 = new Person('zhang',30,'java');
(4) Prototype model:
function Person(){}
Person.prototype.name = 'zhang';
Person.prototype.age = '22';
Person.prototype.job = 'html5';
var person1 = new Person();
2-3 Judgment of data type:
2-3-1: typeof
Generally, the typeof operator is used to determine which basic type of a value belongs to.
Disadvantage : Cannot distinguish
object type
typeof 'seymoe' // 'string'
typeof true // 'boolean'
typeof 10 // 'number'
typeof Symbol() // 'symbol'
typeof null // 'object' 无法判定是否为 null
typeof undefined // 'undefined'
typeof {} // 'object'
typeof [] // 'object'
typeof(() => {}) // 'function'
why typeof null is object:
When js stores variables in the bottom layer, it will store its type information in the low 1-3 bits of the machine code of the variable
000: Object
010: Floating point number
100: string
110: Boolean
1: integer
However, for undefined and null, the information storage for these two values is a bit special.
null: all machine codes are 0
undefined: expressed as an integer of −2^30
Therefore, typeof has a problem when judging null. Since all machine codes of null are 0, it is directly treated as an object.
2-3-2:instanceof
Determine the object type: test whether the prototype of the constructor function appears on the prototype chain of the detected object.
Disadvantages: it is impossible to judge whether a value belongs to an array or an ordinary object
[] instanceof Array // true
({}) instanceof Object // true
(()=>{}) instanceof Function // true
let arr = []
let obj = {}
arr instanceof Array // true
arr instanceof Object // true
obj instanceof Object // true
在这个例子中,arr 数组相当于 new Array() 出的一个实例,
所以 arr.__proto__ === Array.prototype,
又因为 Array 属于 Object 子类型,
即 Array.prototype.__proto__ === Object.prototype,
所以 Object 构造函数在 arr 的原型链上
Can't judge the original type
console.log(true instanceof Boolean);// false
console.log(undefined instanceof Object); // false
console.log(arr instanceof Array); // true
console.log(null instanceof Object); // false
console.log({} instanceof Object); // true
console.log(function(){} instanceof Function);// true
2-3-3: Object.prototype.toString.call()
Almighty, almost able to judge
Object.prototype.toString.call({})// '[object Object]'
Object.prototype.toString.call([])// '[object Array]'
Object.prototype.toString.call(() => {})// '[object Function]'
Object.prototype.toString.call('abc')// '[object String]'
The original type is passed in but the result can be determined because the value is wrapped.
"So, what is the packaging object:"
The so-called "packaged objects" refer to the three native objects of Number, String, and Boolean that correspond to numeric values, strings, and Boolean values, respectively. These three primitive objects can turn (wrap) primitive values into objects.
3 js operator:
3 js operator:
3-1 delete operator
The delete operator is used to delete
object attributes or
array elements. If
successfully deleted or the deleted target
does not exist, delete will return
true
.
However, not all attributes can be deleted:
Some built-in core and client properties cannot be deleted
Variables declared by var statement cannot be deleted
The function defined by the function statement cannot be deleted.
E.g:
var o = { x: 1, y: 2}; // 定义一个对象
console.log(delete o.x); // true,删除一个属性
console.log(delete o.x); // true,什么都没做,x 在已上一步被删除
console.log("x" in o); // false,这个属性在对象中不再存在
console.log(delete o.toString); // true,什么也没做,toString是继承来的
console.log(delete 1); // true,无意义
var a = [1,2,3]; // 定义一个数组
console.log(delete a[2]); // true,删除最后一个数组元素
console.log(2 in a); // false,元素2在数组中不再存在
console.log(a.length); // 3,数组长度并不会因 delete 而改变
console.log(a[2]); // undefined,元素2所在的位置被空了出来
console.log(delete a); // false,通过 var 语句声明的变量不能删除
function f(args){} // 定义一个函数
console.log(delete f); // false,通过 function 语句声明的函数不能删除
3-2 void operator
The void operator can be applied to any table type expression, the expression will be executed, but the result of the
will be ignored and
return undefined.
E.g:
void 0;
void "you are useless?";
void false;
void [];
void /(useless)/ig;
void function(){ console.log("you are so useless?"); }
void alert(1)
// always return undefined
3-3 ++ - operator
++ - Increment and decrement operators are borrowed from the C language. They are divided into pre-type and post-position, and their function is to change the value of a variable.
E.g:
var a = 5;
console.log(a++); // 5 后加表不加
console.log(a); // 6
console.log(++a); // 7 先加,都有加
console.log(a) // 7
console.log(a--); // 7
console.log(a) // 6
console.log(--a); // 5
console.log(a) // 5
kinky skills :
first family has a family, but the latter family does not show family (the plus sign is in the front, and the expression itself is added by 1; the plus sign is in the back, the expression does not add 1, and the expression itself is increased by 1), and the subtraction is the same Rationale.
3-4 valueOf
var a = '你好', b = 1, c = [], d = {}, e = function (){}
a.valueOf() // '好'
b.valueOf() // 1
c.valueOf() //[]
d.valueOf() // {}
e.valueOf() //ƒ (){}
3-5 + and-
"+" operator, if one of them is a string, then all are converted to a string and then perform string splicing
"-" operator, conversion to number, subtraction (-a, a * 1 a/1) can be implicitly coerced
[] + {} // "[object Object]"
{} + [] // 0
1 + true //2
1 + false //1
4 RAM
4 RAM
4-1 execution context
4-1 execution context
When the code is running, a corresponding execution environment will be generated. In this environment, all variables will be raised in advance (variable promotion), some are assigned directly, and some are the default value undefined, and the code starts to execute from top to bottom. It's called the execution context.
"There are three execution environments":
1. Global environment: the environment where the code enters first
2. Function environment: the environment in which the function is executed when it is called
3.eval function
"Execution context features:"
1. Single thread, running on the main process
2. Synchronous execution, executed in order from top to bottom
3. There is only one global context, and the stack will be popped up when the browser is closed
4. There is no limit to the number of execution contexts of functions
5. Each time the function is called, a new execution context will be generated
"Execute 3 stages:"
1. Creation phase
(1). Generate variable objects
(2). Establish a scope chain
(3). Make sure this points to
2. Execution stage
(1). Variable assignment
(2). Function reference
(3). Execute other codes
3. Destruction stage
(1). Pop out of the stack after execution, waiting for recovery to be destroyed
4-2 Stack
4-2 Stack
"concept:"
Stack: The stack will automatically allocate
, which is automatically released
; it stores the basic
, a simple data segment, and occupies a fixed size space of
Heap:
dynamically allocated memory, the size is variable and
will not be automatically released. Store the
reference
objects that may be composed of multiple values, are stored in the heap memory
5 Garbage collection mechanism
5 Garbage collection mechanism
It is said on MDN: Since 2012, all modern browsers have used the mark-clear garbage collection algorithm. All improvements to the js garbage collection algorithm are based on the improvement of the mark-sweep algorithm
"What is garbage:" general,
not
object reference is rubbish, it is to clear. But there is an exception. If several objects refer to each other to form a ring, but the root cannot access them, they are also garbage (reference counting method cannot clear them)
``Several algorithms for garbage collection:''
5-1 Reference counting method
5-1 Reference counting method
concept : Record how many "programs" are referencing itself, and when the referenced value is 0, start to clear it.
Advantage :
immediately reclaim garbage. When the referenced value is
0
, the object will immediatelyfree space to the
free list, that is to say. When it becomes garbage,
immediately recycled.
Because it is instant recovery, then the 'program' does not pause to use the GC for a long time alone, then
maximum pause time
very short.
No need to traverse all active and inactive objects in the heap
disadvantage :
The counter needs
occupy a large
position, because the upper limit of being quoted cannot be estimated. For example, there may be 32-bit objects that are 2 to the 32th power referencing an object at the same time, then the counter needs 32 bits.
The biggest disadvantage is that
cannot solve the problem that circular references cannot be recycled. This is the problem that occurred before IE9 in the previous article.
5-2 Mark removal method
5-2 Mark removal method
The garbage collection process of GC is mainly divided into two stages
marking stage : all
active objects
marked with 160b3936909cd4.
Clear phase :
without marking (that is, inactive object)
.
advantage:
Simple to implement, marking means either marking or not marking, so only one binary digit can be expressed
Solved the circular reference problem
Disadvantages
Cause fragmentation (somewhat similar to disk fragmentation)
There are many passes during redistribution. If the appropriate memory block size has not been found, the free linked list (the linked list formed by the addresses of all the free address spaces in the heap) will be traversed to the end.
5-3 Copy Algorithm
5-3 Copy Algorithm
From
a memory space into two parts, one part is 060b3936909dc7 space, the other part isTo
spaceCopy the
activity object
From space to the
To space
Free up the entire
From
spaceThen exchange
From space and To space, and then complete a GC.
6 memory leak
6 memory leak
"concept:" application
memory is not
timely recovery of lost, resulting in system
memory
waste, causing the program
speed
slow down or even system crashes and other serious
consequences
"Scenario where the memory leak occurred:"
(1) Unexpected global variable
function leaks(){
leak = 'xxxxxx';//leak 成为一个全局变量,不会被回收
}
(2) Forgotten timer
setTimeout and setInterval are dedicated threads
to maintain its
life cycle. If a timer is used on a page, when the page is destroyed, these timers are not manually released and cleared, then these timers are still alive. Written
(3) Improper use of closure
var leaks = (function(){
var leak = 'xxxxxx';// 被闭包所引用,不会被回收
return function(){
console.log(leak);
}
})()
(4) Missing DOM element
<div id="container">
</div>
$('#container').bind('click', function(){
console.log('click');
}).remove();//dom移除了,但是js还持有对它的引用
solve:
$('#container').bind('click', function(){
console.log('click');
}).off('click').remove();
//把事件清除了,即可从内存中移除
(5) Network callback
"How to monitor memory leaks"
Use the console
Click here for details
7 scope
7 scope
extends :
JavaScript is a dynamic language. Unlike Java, JavaScript can define global variables and local variables at will. Each function is a scope. When the function is executed, it will look up the current scope first, and then step up.
JavaScript is a static scope. When querying a variable, the value of the variable is determined by the position of the function definition, and has nothing to do with the scope of execution.
ES6 already has block-level scope, and variables defined with let and const will not be promoted.
concept :
scope : the effective scope of the variable or function
scope chain : We need to find a variable value, we will first search in the current scope, if we can't find it, we will go to the upper level, if we find it, we will return to stop the search, return the searched value, this kind of upward The chain relationship to find is called scope
7-1 Related Cases
7-1 Related Cases
(1) Variable promotion/variable is determined by the position when the function is defined
var a = 1;
function fn() {
console.log('1:' + a);
var a = 2;
bar()
console.log('2:' + a)
}
function bar() {
console.log('3:' + a)
}
fn()
Print separately: 1:undefined 3:1 2:2
"Analysis:"
The first a printed value is 1:undefined instead of 1. Because we defined the variable a in fn(), the variable defined with var will be promoted to the top of the current scope (that is, the top of the current function scope), but the assignment is still in place, so it is undefined.
The second a printed value is 3:1 instead of 2. Because the function bar is defined in the global scope, the scope chain is bar -> global. A is not defined in bar, so it will look up the scope chain and find a in global. Note : The search is performed in the execution context defined
The third a printed value is 2:2. The scope chain where this sentence is located is fn -> global. Executing console.log('2:' + a) will first search for a in the fn scope, find a, and it has been assigned a value of 2, so the result is 2. .
(2) Variable assignment
var a = 1;
function fn() {
console.log('1:' + a);
a = 2
}
a = 3;
function bar() {
console.log('2:' + a);
}
fn();
bar();
Print separately: 1:3 2:2
"Analysis:"
The first printed value is 1:3. First of all, a = 2 in fn is to assign a value to the variable a, not to declare the variable. Then, execute the function fn. At this time, a has been assigned a value of 3. Note that fn() is executed after a=3.
The second printed value is 2:2. The scope chain that the function bar can access is bar->global. When the function bar is executed, since fn() is executed before bar to modify a to 2, so the a obtained at this time is 2.
(3) Global variable declaration in advance
if(!(a in window)){
var a = 10;
}
console.log(a);
Print: undefined
"Analysis:"
Is equivalent to:
var a;
if(!(a in window)){
a = 10;
}
console.log(a);
Variables defined with var will be promoted to the top of the current scope (that is, the current global scope), so a will be declared in advance to the window, but the value is still in place, that is, undefined. So if get is a in window is ture, so do not go inside the assignment console.log(a) == undefined
A variant of the previous example:
(function(){
var x = c = b = {a:1}
})()
console.log(c,b) // {a: 1} {a: 1}
console.log(x.a); // error , x is not defined
Note : x is declared in the function and is a local variable. C and b are not declared and assigned directly, so they are global variables. The assignment process is from right to left, that is, b={a:1},c=b,x=c
( 4) Variable promotion/operator order
(function(){
var a = b = 3;
})()
console.log(typeof a === "undefined"); // true
console.log(typeof b === "undefined"); // false
console.log(typeof b === "number" && b ===3); // true
// What is involved here is the issue of immediate execution and closure, as well as variable promotion, and the direction of operator execution (= sign from right to left)
// That function can be broken down like this
(function()
var a; /* 局部变量,外部没法访问*/
b = 3; /* 全局变量,so . window.b === 3 , 外部可以访问到*/
a = b;
})()
(5) Variable promotion/operator order
var x = 1;
if (function f(){console.log(2)}) {
x += typeof f;
}
console.log(x); // 1undefined
//Because the function body will be run as an expression in (), the fn function does not work and the function will not be executed.
//Finally, the expression is converted to true, f is not declared (the above function does not work), the value is undefined
"Knowledge Points:"
(1) In JavaScript, variables defined by let and const have the characteristics of block-level scope.
(2) Variables defined by var will be promoted in its own scope, while variables defined by let and const will not.
(3) Every JavaScript program has a global scope, and every time a function is created, a scope is created.
(4) When creating functions, nest these functions, and their scopes will also be nested to form a scope chain. The child scope can access the parent scope, but the parent scope cannot access the child scope.
(5) When executing a function, if we need to find the value of a certain variable, we will search in the scope chain where the function was defined. Once we find the required variable, we will stop searching upwards.
(6)
"The value of a variable is determined by the position when the function is defined" is ambiguous. To be precise, when looking for a variable, it is the scope chain where
defined when the function is defined.
8 Closure
8 Closure
"Concept:"
Closure is a function that can be accessed
other functions
scope of
variables
"Application scenario:"
Function stabilization
Encapsulate private variables
The entire execution process of JavaScript code is divided into two stages, the
code compilation stage and the
code execution stage. The compilation stage is completed by the compiler to translate the code into executable code. At this stage, the
scope rules will be determined. The execution phase is completed by the engine. The main task is to execute executable code at
. The execution context is created in this phase.
9 this
9 this
9-1 The point of this:
9-1 The point of this:
ES5:
this always points to the object
that called it last
ES6 arrow function:
The this of the arrow function always points to the this
function is defined
not when it is executed.
9-2 How to change the point of this:
9-2 How to change the point of this:
Use ES6 arrow functions
Use _this = this inside the function
Use apply, call, bind
new instantiates an object
Case 1:
var name = "windowsName";
var a = {
name : "Cherry",
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( function () {
this.func1()
},100);
}
};
a.func2() // this.func1 is not a function
If the arrow function is not used, an error will be reported, because the object that finally calls setTimeout is
window, but there is no func1 function in window. Can be seen as window.setTimeout
Case 2:
var webName="long";
let func=()=>{
console.log(this.webName);
}
func();//long
//The arrow function is declared in the global scope, so it captures this in the global scope, and this points to the window object
Case 3:
var webName = "long";
function wrap(){
let func=() => {
console.log(this.webName);
}
func();
}
wrap();//long
//When the wrap function is executed, the arrow function func is defined in wrap, and func will find the this of the nearest non-arrow function
//That is the this of wrap, and this in the scope of the wrap function points to the window object.
9-3 Arrow function:
9-3 Arrow function:
"Tips:" As we all know, the arrow function of ES6 can avoid the pitfall of using this in ES5. The this of the
arrow function always points to the this when
defined, and when
not executed.
The arrow function needs to remember this sentence: "There is no this binding in the arrow function, and its value must be determined by looking up the scope chain (the arrow function itself does not have this, but it can capture other people's this for its own use when it is declared.) , If the arrow function is contained by a non-arrow function, this is bound to the this of the non-arrow function of the nearest layer, otherwise, this is undefined".
Features :
Without this
No arguments
Cannot be called by the new keyword
No new.target
No prototype
No super
10 Prototypes and prototype chain
10 Prototypes and prototype chain
10-1 Background:
10-1 Background:
A function can be regarded as a class. The prototype is an attribute of all classes. The function of the prototype is to add a unified method to each object of this class.
10-2 Basic concepts
10-2 Basic concepts
"prototype:" each
function will
have this
property, to emphasize here that is a function,
ordinary objects are
do not have this property (Why here that ordinary objects, because the JS inside, everything is an object, so The ordinary objects here do not include function objects). It is the prototype object of the constructor;
"" proto ":" each
object
have this
property, to emphasize here that the object is the same, because the function is an object, the function also has this property. It points to the prototype object of the constructor;
"constructor:" This is an attribute on the prototype object that points to the constructor.
var webName = "long";
// Pig的构造函数
function Pig(name, age) {
this.name = name;
this.age = age;
}
// 创建一个Pig的实例,小猪佩奇
var Peppa = new Pig('Peppa', 5);
Peppa.__proto__ === Pig.prototype。 //true
Pig.__proto__ === Function.prototype //true
Pig.prototype.constructor === Pig //true
kinky tricks: Han Xin pair drink (display prototype of function = hermit prototype of the object)
click here for details
10-3 What is prototypal inheritance
10-3 What is prototypal inheritance
An object may be used
another object of
attributes or
method, it is called
inheritance.
Specifically, by setting the prototype
this object to another
object, so according to the rules of the prototype chain, if an object property is searched and it does not exist, another object will be searched, which is equivalent to one object can use another The properties and methods of the object are gone.
11 shades of copy
11 shades of copy
11-1 Shallow clone
11-1 Shallow clone
function shallowClone(obj) {
let cloneObj = {};
for (let i in obj) {
cloneObj[i] = obj[i];
}
return cloneObj;
}
11-2 Deep clone
11-2 Deep clone
Deep clone:
Consider the basic type
Reference type
RegExp, Date, and functions are not JSON safe
The constructor will be lost, all constructors point to Object
Cracking circular references
function deepCopy(obj) {
if (typeof obj === 'object') {
var result = obj.constructor === Array ? [] : {};
for (var i in obj) {
result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];
}
} else {
var result = obj;
}
return result;
}
12 array
12 array
12-1 Array de-duplication
12-1 Array de-duplication
1. New Set of
let arr=[1,2,2,3]
let arrNew=[...new Set(arr)]
console.log(arrNew)//[1,2,3]
2. Traverse the old array to add a unique element to the new array
function unique(arr) {
var newArr = []
for (var i = 0; i < arr.length; i++) {
f (newArr.indexOf(arr[i])===-1) {//方式1
newArr.push(arr[i])
}
// if (!newArr.includes(arr[i])) {//方式2
// newArr.push(arr[i])
//}
}
return newArr
}
console.log(unique(arr))//[1,2,3]
3. Use Map data structure to remove
function unique(){
let map =new Map()
let arr=new Array()
for(let i=0;i<arr.length;i++){
if(map.has(arr[i])){//如果有key值,它是把元素值作为key
map.set(arr[i],true)
}else{
map.set(arr[i],false)//如果没有该key值
array.push(arr[i])
}
}
return array
}
console.log(unique([1,2,2,3]))
resolution:
Store each element as a key value in the Map. Since the same key will not appear in the Map, the final result after deduplication is obtained.
12-2 Array expansion
12-2 Array expansion
1. flat method
let arr = [1,2,[3,4],[5[6,7]]]
let arr1 = arr.flat(Infinity)//[1,2,3,4,5,6,7]
2.join,split
let arr = [1,2,[3,4],[5[6,7]]]
let arr1 = arr.join().split(",") //["1", "2", "3", "4", ""]
3.toString,split
let arr = [1,2,[3,4],[5[6,7]]]
let arr1 = arr.toString().split(",") //["1", "2", "3", "4", ""]
12-3 Array merge
12-3 Array merge
1. es6 expand and merge
let arr1 = [1,2]
let arr2 = [3,4]
let arr = [...arr1,...arr2]//[1,2,3,4]
2. concat
let arr = arr1.concat(arr2)
12-4 Judgment array
12-4 Judgment array
instanceof
console.log(arr instanceof Array)
constructor
console.log(arr.constructor === Array)
Array.isArray
console.log(Array.isArray(arr))
toString
console.log(Object.prototype.toString.call(arr) === "[object Array]")
Determine whether there is an array push method
console.log(!!arr.push && !!arr.concat)
13 objects
13 objects
13-1 How to determine whether an object is an empty object
13-1 How to determine whether an object is an empty object
1. Convert the json object into a json string, and then judge whether the string is "{}"
var data = {};
var b = (JSON.stringify(data) == "{}"); //true
2.for in loop judgment
var obj = {};
var b = function() {
for(var key in obj) {
return false;
}
return true;
}
b();//true
3.jquery's isEmptyObject method
This method is that jquery encapsulates 2 methods (for in), and it needs to rely on jquery when using it.
var data = {};
var b = $.isEmptyObject(data);
alert(b);//true
4.Object.getOwnPropertyNames() method
This method uses the getOwnPropertyNames method of the Object object to obtain the property names in the object, store them in an array, and return the array object. We can judge whether the object is empty by judging the length of the array
Note: This method is not compatible with ie8, other browsers have not been tested
var data = {};
var arr = Object.getOwnPropertyNames(data);
alert(arr.length == 0);//true
5. Use ES6's Object.keys() method
Similar to the 4 method, it is a new method of ES6, and the return value is also an array of attribute names in the object
var data = {};
var arr = Object.keys(data);
alert(arr.length == 0);//true
13 v8 engine
13 v8 engine
13-1 v8 garbage collection
13-1 v8 garbage collection
"Background:"
V8's garbage collection strategy is based on the
generational collection mechanism, which is based on the
generation hypothesis.
This hypothesis has two characteristics :
Most
newborn subjects tend to
early at 160b393690a988;
immortal objects, will
live too
longer.
Based on this theory, modern garbage collection algorithms divide the memory into generations according to the survival time of objects, and use different efficient algorithms for garbage collection for different generations of memory.
"V8 memory generation"
In V8, the memory is divided into
(new space) and
old (old space).
Their characteristics are as follows:
Cenozoic : The object's
survival time
shorter. Newborn objects or objects that have been garbage collected
.
Old generation : Object
longer survival time 160b393690aa2d.
experienced one or more garbage collections of 160b393690aa2e.
"V8 heap space"
The space of the V8 heap is equal to the space of the young generation plus the space of the old generation. We can use the --max-old-space-size command to set the maximum space of the old generation, and the --max-new-space-size command to set the maximum space of the young generation. The space size of the old generation and the
generation is set when the program 160b393690aa51 is initialized, and cannot be changed dynamically once it takes effect.
node --max-old-space-size=1700 test.js // The unit is MB
node --max-new-space-size=1024 test.js // unit is KB
By default, the old generation size of 64-bit system is 1400M, and the size of 32-bit system is 700M.
For the new generation, it consists of two reserved_semispace_size. The size of each reserved_semispace_size is different on machines with different bits. The default settings are 16MB and 8MB for 64-bit and 32-bit systems, respectively. We summarize the space size of the young generation, the old generation, and reserved_semispace_size in the following table.
Type\System Digits | 64 bit | 32 bit |
---|---|---|
Old generation | 1400MB | 700MB |
reserved_semispace_size | 16MB | 8MB |
New generation | 32MB | 16MB |
14 event loop
14 event loop
14-1 What is the event loop
14-1 What is the event loop
15 Advantages and disadvantages of strict mode
15 Advantages and disadvantages of strict mode
15-1 Concept
15-1 Concept
ECMAScript a five-introduced to better method of error checking code is introduced, most browsers now been implemented. In this mode makes Javascript more stringent operated under conditions
15-2 Advantages
15-2 Advantages
It is no longer possible to accidentally create global variables.
The assignment operation that causes silent failure (silently fail, that is, no error is reported and no effect) throws an exception.
An exception will be thrown when trying to delete a non-deletable attribute (the previous operation will not have any effect).
The parameter name of the function is required to be unique.
In the global scope, the value of this is undefined.
Some common coding errors are caught and exceptions are thrown.
Disable confusing or suboptimal features.
15-3 Disadvantages
15-3 Disadvantages
Many features that developers have become accustomed to are missing.
Cannot access function.caller and function.arguments.
Combining scripts written in different strict modes may cause problems.
16 ES6
16 ES6
16-1 Background
16-1 Background
EC version | release time | New features |
---|---|---|
2009(ES5) | November 2009 | Expanded the functions of Object, Array, Function and other new features |
2015(ES6) | June 2015 | Classes, modularity, arrow functions, default values of function parameters, etc. |
2016(ES7) | March 2016 | includes, exponential operator |
2017(ES8) | June 2017 | sync/await, Object.values(), Object.entries(), String padding, etc. |
16-2 Common Features
16-2 Common Features
class
Modular
Arrow function
Function parameter default value
Template string
Destructuring assignment
Spread operator
Object property shorthand
Promise
Let and Const
"(1) class"
In traditional javascript, there are only objects and no concept of classes.
It is an object-oriented language based on prototypes. The characteristic of the prototype object is to share its own properties with the new object.
Compared with other traditional object-oriented languages, this kind of writing is very unique! It's very confusing!
If you want to generate an object instance, you need to define a constructor first, and then complete it through the new operator.
The following example demonstrates the evolution from constructor to class:
constructor -
function Person(name,age) {
this.name = name;
this.age=age;
}
Person.prototype.say = function(){
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
var obj=new Person("laotie",88);
//通过构造函数创建对象,必须使用new 运算符
console.log(obj.say());//我的名字叫laotie今年88岁了
ES6 introduces the concept of Class (class), and classes can be defined through the class keyword.
The appearance of this keyword makes it clearer in object writing, more like an object-oriented language.
If you change the previous code to ES6, it will look like this:
class--
class Person{//定义了一个名字为Person的类
constructor(name,age){//constructor是一个构造方法,用来接收参数
this.name = name;//this代表的是实例对象
this.age=age;
}
say(){//这是一个类的方法,注意千万不要加上function和逗号
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
}
var obj=new Person("laotie",88);
console.log(obj.say());//我的名字叫laotie今年88岁了
console.log(typeof Person);//function--类实质上就是一个函数
console.log(Person===Person.prototype.constructor);//true
//类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法!
Note:
When declaring a method in a class, do not add the function keyword to the method
Do not use commas to separate methods, otherwise an error will be reported
There is no variable promotion for class, so it needs to be defined before use. Because ES6 does not promote the declaration of the class to the head of the code, but ES5 is not the same, ES5 has variable promotion, you can use it first, and then define it.
//ES5可以先使用再定义,存在变量提升
new A();
function A(){
}
//ES6不能先使用再定义,不存在变量提升 会报错
new B();//B is not defined
class B{
}
"(2) Module"
background
In the previous javascript, there was no concept of modularity. If you want to perform modular operations, you need to introduce a third-party class library. With the development of technology, the front-end and the back-end are separated, and the front-end business becomes more and more complicated. It was not until ES6 brought modularity that javascript supported modules for the first time. ES6 modularity is divided into two modules
export and
import.
The usage of export
In each ES6
module that is a
files, variables defined in file, function, object
outside is
can not be obtained. If you want the content of the module to be read externally, you must use
export
to expose it (output)
Let's first look at an example to modularize a variable.
//我们先来创建一个test.js文件,来对这一个变量进行输出:
export let myName="laowang";
//然后可以创建一个index.js文件,以import的形式将这个变量进行引入:
import {myName} from "./test.js";
console.log(myName);//laowang
If you want to output multiple variables of
you can package these variables into
objects for modular output:
let myName="laowang";
let myAge=90;
let myfn=function(){
return "我是"+myName+"!今年"+myAge+"岁了"
}
export {
myName,
myAge,
myfn
}
******************************接收的代码调整为*********************
import {myfn,myAge,myName} from "./test.js";
console.log(myfn());//我是laowang!今年90岁了
console.log(myAge);//90
console.log(myName);//laowang
If you don't want to expose the variable name in the module, you can do it through as:
let myName="laowang";
let myAge=90;
let myfn=function(){
return "我是"+myName+"!今年"+myAge+"岁了"
}
export {
myName as name,
myAge as age,
myfn as fn
}
/******************************接收的代码调整为**********************/
import {fn,age,name} from "./test.js";
console.log(fn());//我是laowang!今年90岁了
console.log(age);//90
console.log(name);//laowang
You can also directly import the entire module and modify the above receiving code to:
import * as info from "./test.js";//通过*来批量接收,as 来指定接收的名字
console.log(info.fn());//我是laowang!今年90岁了
console.log(info.age);//90
console.log(info.name);//laowang
Default export (default export) A module can only have one default export. For the default export, the name of the import can be inconsistent with the name of the export.
/******************************导出**********************/
export default function(){
return "默认导出一个方法"
}
/******************************引入**********************/
import myFn from "./test.js";//注意这里默认导出不需要用{}。
console.log(myFn());//默认导出一个方法
You can put all the variables that need to be exported into an object, and then export through default export
/******************************导出**********************/
export default {
myFn(){
return "默认导出一个方法"
},
myName:"laowang"
}
/******************************引入**********************/
import myObj from "./test.js";
console.log(myObj.myFn(),myObj.myName);//默认导出一个方法 laowang
Also supports mixed export
/******************************导出**********************/
export default function(){
return "默认导出一个方法"
}
export var myName="laowang";
/******************************引入**********************/
import myFn,{myName} from "./test.js";
console.log(myFn(),myName);//默认导出一个方法 laowang
Renaming export and import If the variable names in multiple imported files are the same, there will be a naming conflict problem. To solve this problem, ES6 provides a renaming method. You can do this when importing names:
/******************************test1.js**********************/
export let myName="我来自test1.js";
/******************************test2.js**********************/
export let myName="我来自test2.js";
/******************************index.js**********************/
import {myName as name1} from "./test1.js";
import {myName as name2} from "./test2.js";
console.log(name1);//我来自test1.js
console.log(name2);//我来自test1.js
"(3) Arrow function"
Check the 1-5-3 arrow function section:
The this of the arrow function always points to the this when the function was defined, not when it was executed. The arrow function needs to remember this sentence: "There is no this binding in the arrow function, and its value must be determined by looking up the scope chain. If the arrow function is contained by a non-arrow function, then this is bound to the nearest non-arrow function The this, otherwise, this is undefined".
「(4) Default value of function parameters」
ES6 supports setting default values when defining functions:
function foo(height = 50, color = 'red')
{
// ...
}
Do not use the default value:
function foo(height, color)
{
var height = height || 50;
var color = color || 'red';
//...
}
This is generally no problem, but when the Boolean value of the parameter is false, there will be a problem.
For example, we call the foo function like this: foo(0, "")
Because the Boolean value of 0 is false, the value of height will be 50. Similarly, the value of color is'red'. So, the default value of function parameters can not only make the code more concise but also avoid some problems.
「(5) Template String」
ES6 supports the definition of function ES6 supports template strings, making the splicing of strings more concise and intuitive.
Do not use template strings:
var name = 'Your name is ' + first + ' ' + last + '.'
Use template strings:
var name = `Your name is ${first} ${last}.`
In ES6 by
${}
can be completed string concatenation, simply variables in
large brackets in.
「(6) Deconstruction Assignment」
Deconstruction assignment syntax is an expression of JavaScript, it can easily from
array or
fast object
extract the value assigned to the defined
variables.
Get the value in the array
//从数组中获取值并赋值到变量中,变量的顺序与数组中对象顺序对应。
var foo = ["one", "two", "three", "four"];
var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
//如果你要忽略某些值,你可以按照下面的写法获取你想要的值
var [first, , , last] = foo;
console.log(first); // "one"
console.log(last); // "four"
//你也可以这样写
var a, b; //先声明变量
[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
//如果没有从数组中的获取到值,你可以为变量设置一个默认值。
var a, b;
[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7
//通过解构赋值可以方便的交换两个变量的值。
var a = 1;
var b = 3;
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
Get the value in the object
const student = {
name:'Ming',
age:'18',
city:'Shanghai'
};
const {name,age,city} = student;
console.log(name); // "Ming"
console.log(age); // "18"
console.log(city); // "Shanghai"
"(7) Extension Operator"
In ECMAScript 2018, the extension operator adds support for objects for the disassembly of objects and arrays
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
var clonedObj = { ...obj1 };
// 克隆后的对象: { foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 };
// 合并后的对象: { foo: "baz", x: 42, y: 13 } 相同属性会进行覆盖
//我们可以这样合并数组:
var arr1=['a','b','c'];
var arr2=[...arr1,'d','e']; //['a','b','c','d','e']
//展开运算符也可以用在push函数中,可以不用再用apply()函数来合并两个数组:
var arr1=['a','b','c'];
var arr2=['d','e'];
arr1.push(...arr2); //['a','b','c','d','e']
//用于解构赋值
let [arg1,arg2,...arg3] = [1, 2, 3, 4];
arg1 //1
arg2 //2
arg3 //['3','4']
//展开运算符既然能合并数组,自然也能解构数组,不过要注意,解构赋值中【展开运算符】只能用在【最后】:
let [arg1,...arg2,arg3] = [1, 2, 3, 4]; //报错
「(8)
ES6 allows us to not specify the property name when setting the properties of an object.
Does not use ES6
const name='Ming',age='18',city='Shanghai';
const student = {
name:name,
age:age,
city:city
};
console.log(student);//{name: "Ming", age: "18", city: "Shanghai"}
//对象中必须包含属性和值,显得非常冗余。
Use ES6
const name='Ming',age='18',city='Shanghai';
const student = {
name,
age,
city
};
console.log(student);//{name: "Ming", age: "18", city: "Shanghai"}
//对象中直接写变量,非常简洁。
「(9) Promise」 What is Promise
Promise is a
solution for
asynchronous programming, which is more reasonable and more powerful than the traditional asynchronous solution
callback function and
event. It has now been incorporated into the specification by ES6.
Here are a few cases to deepen the understanding of promises:
(1) The Promise constructor is executed synchronously. Then is asynchronous
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
//运行结果:1 2 4 3
Analysis: The
Promise
constructor is synchronously by
promise.then
, and the function in is executed asynchronously by 160b393690b300.
(2) Once the promise status is changed, it cannot be changed again
const promise = new Promise((resolve, reject) => {
resolve('success1')
reject('error')
resolve('success2')
})
promise
.then((res) => {
console.log('then: ', res)
})
.catch((err) => {
console.log('catch: ', err)
})
//运行结果:then: success1
Resolution: The resolve or reject in the constructor is only
the first execution of
Calling
multiple times by 160b393690b337 has no effect on
. Once the promise state changes, it cannot be changed.
(3) .then or .catch will return a new promise
Promise.resolve(1)
.then((res) => {
console.log(res)
return 2
})
.catch((err) => {
return 3
})
.then((res) => {
console.log(res)
})
//运行结果:1 2
Resolution: Promises can be chained. When it comes to chain calls, we usually think of implementing it through return this, but Promise is not implemented in this way. Every time a promise is called .then or .catch, a new promise is returned, thus realizing a chain call.
(4) The Promise constructor is executed only once
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('once')
resolve('success')
}, 1000)
})
const start = Date.now()
promise.then((res) => {
console.log(res, Date.now() - start)
})
promise.then((res) => {
console.log(res, Date.now() - start)
})
//运行结果:once
success 1005
success 1007
Resolution: The .then or .catch of a promise can be called multiple times, but here the Promise constructor is only executed once. In other words, once the internal state of the promise changes (the first call to .then changes), and there is a value, then each subsequent call to .then or .catch will get the value directly.
(5) .then or .catch will return a new promise
Promise.resolve()
.then(() => {
return new Error('error!!!')
})
.then((res) => {
console.log('then: ', res)
})
.catch((err) => {
console.log('catch: ', err)
})
//运行结果:then: Error: error!!!
at Promise.resolve.then (...)
at ...
Analysis: Returning an error object in .then or .catch will not throw an error, so it will not be caught by subsequent .catch, and it needs to be changed to one of them:
return Promise.reject(new Error('error!!!'))
throw new Error('error!!!')
Because returning any non-promise value will be wrapped into a promise object, that is, return new Error('error!!!') is equivalent to return Promise.resolve(new Error('error!!!')).
(6) The value returned by .then or .catch cannot be the promise itself
const promise = Promise.resolve()
.then(() => {
return promise
})
promise.catch(console.error)
//运行结果:TypeError: Chaining cycle detected for promise #<Promise>
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
at Function.Module.runMain (module.js:667:11)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:607:3
Resolution: The value returned by .then or .catch cannot be the promise itself, otherwise it will cause an endless loop.
(7) .then function return value type and parameter passing
Promise.resolve(2) // resolve(2) 函数返回一个Promise<number>对象
.then(x=>{
console.log( x ); // 输出2, 表示x类型为number且值为2,也就是上面resolve参数值
return "hello world"; // 回调函数返回字符串类型,then函数返回Promise<string>
}) // then函数返回Promise<string>类型
.then(x=>{
console.log( x ); // 输出hello world,也就是上一个then回调函数返回值,表明上一个then的返回值就是下一个then的参数
}) // then函数回调函数中没有返回值,则为Promise<void>
.then(x=>{ // 前面的then的回调函数没有返回值所以这个x是undefined
console.log( x ); // undefined
}) // Promise<void>
.then(()=>{ // 前面没有返回值,这里回调函数可以不加返回值
return Promise.resolve("hello world"); // 返回一个Promise<string>类型
}) // 这里then的返回值是Promise<string>
.then(x=>{ // 虽然上面的then中回调函数返回的是Promise<string>类型但是这里x并不是Promise<string>类型而是string类型
console.log(x); // hello world
return Promise.resolve(2); // 返回一个Promise<number>类型对象
}) // 返回Promise<number>类型
(8) The parameter of .then or .catch is expected to be a function, passing in a non-function will cause value penetration.
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log) //1
Analysis: The parameter of .then or .catch is expected to be a function, and value penetration occurs when a non-function is passed in.
(9) .catch is equivalent to shorthand for .then (the second parameter of .then is omitted)
Promise.resolve()
.then(function success (res) {
throw new Error('error')
}, function fail1 (e) {
console.error('fail1: ', e)
})
.catch(function fail2 (e) {
console.error('fail2: ', e)
})
//运行结果:fail2: Error: error
at success (...)
at ...
Analysis: .then can receive two parameters, the first is a function that handles success, and the second is a function that handles errors. .catch is also equivalent to a .then, except that the second parameter of .then is omitted, but there is one point to note in their usage: the second error handling function of .then cannot capture the first successfully processed function The error thrown, and the subsequent .catch can catch the previous error.
(10) Micro task macro task execution order
process.nextTick(() => {
console.log('nextTick')
})
Promise.resolve()
.then(() => {
console.log('then')
})
setImmediate(() => {
console.log('setImmediate')
})
console.log('end')
//运行结果:end
nextTick
then
setImmediate
Analysis: process.nextTick and promise.then both belong to
microtask
, and setImmediate belongs macrotask
in the check phase of the event loop. The microtask is executed between each stage of the event loop (macrotask), and the microtask is executed once at the beginning of the event loop.
「(10) let and const」
View 1-1js variable declaration
17 Event stream
17 Event stream
The event flow is the order in which webpage elements receive events. The event flow specified by "DOM2 Level Events" includes three stages:
event capture stage,
in the target stage, and
event bubbling stage.
The capture of the first event provides an opportunity to intercept the event.
Then there is the actual target acceptance event.
The last stage is the time bubbling stage, where you can respond to events.
Although the capture phase stipulates that it is not allowed to respond to events in the specification, it will actually be executed, so there are two opportunities to obtain the target object.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件冒泡</title>
</head>
<body>
<div>
<p id="parEle">我是父元素
<span id="sonEle">我是子元素</span>
</p>
</div>
</body>
</html>
<script type="text/javascript">
var sonEle = document.getElementById('sonEle');
var parEle = document.getElementById('parEle');
parEle.addEventListener('click', function () {
alert('父级 冒泡');
}, false);
parEle.addEventListener('click', function () {
alert('父级 捕获');
}, true);
sonEle.addEventListener('click', function () {
alert('子级冒泡');
}, false);
sonEle.addEventListener('click', function () {
alert('子级捕获');
}, true);
</script>
When container elements and nested elements call event handlers in the capturing phase and in the bubbling phase: the events execute the event handlers in the order of the DOM event stream:
Parent capture="child capture="child bubbling="parent bubbling
Click [I am the parent element], and pop up in turn ('parent capture'="'parent bubbling')
Click [I am the parent element] and pop up in turn ('parent capture'="child capture'="'child bubbling'="'parent bubbling')
kinky skills : three stages can be remembered
this 160b393690b61e catching a female cat (capture, target, bubbling)
18 new
18 new
Construct call:
Create a brand new object
This o
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。