1 Data type & judgment method
- JavaScript has two types of data:
- Basic (value) types
- String: Any character string
- Number: any number
- boolean: true/false
- undefined: undefined
- null: null
- Object (reference) type
- Object: any Object
- Function: a special object (that can be executed)
- Array: a special type of object (numeric subscript, internal data ordered)
- judge
- typeof:
- Undefined/value/string/Boolean/function
- Cannot be determined: NULL and Object Object and array
- = = =
- Undefined, null
var a
a = 999
console.log(typeof a ==='number')//true
a = 'july'
console.log(typeof a ==='string')//true
a = true
console.log(typeof a ==='boolean')//true
a = null
console.log(typeof a,a===null)// 'object' is an obvious error
Copy the code
- instanceof:
- Determine the specific type of the object to determine whether A is an instance of B
var b1 = {
b2: [1.'abc'.console.log],
b3: function () {
console.log('b3')
return function () {
return 'fangyuan'}}}console.log(b1 instanceof Object, b1 instanceof Array) // true false
console.log(b1.b2 instanceof Array, b1.b2 instanceof Object) // true true
console.log(b1.b3 instanceof Function, b1.b3 instanceof Object) // true true
console.log(typeof b1.b2, '-- -- -- -- -- -- --) // 'object'
console.log(typeof b1.b3==='function') // true
console.log(typeof b1.b2[2= = ='function')//false
console.log(b1.b3()()) //b3 fangyuan
Copy the code
- Object.prototype.toString
- ToString is a method on an Object prototype that returns the specific type of its caller by default. More strictly speaking, it is the type of the Object to which the toString runtime this refers. The type returned is in the format [Object, XXX], XXX being the specific data type. Basically all object types can be retrieved using this method.
console.log(Object.prototype.toString.call(' '))
console.log(Object.prototype.toString.call(123))
console.log(Object.prototype.toString.call(true))
console.log(Object.prototype.toString.call(undefined))
console.log(Object.prototype.toString.call(null))
console.log(Object.prototype.toString.call(new Function()))
console.log(Object.prototype.toString.call([1.2.4]))
console.log(Object.prototype.toString.call(new Date())
Copy the code
Reference variable assignment
- Two reference variables refer to the same object. One variable modifies the internal data of the object. The other variables see the modified data.
var obj1 = {name:'tom'}
var obj2 = obj1
obj2.age = 12
console.log(obj1.age)/ / 12
function fn(obj){
obj.name = 'lily'
}
fn(obj1)
console.log(obj2.name)//lily
Copy the code
- Two reference variables point to the same object, so that one reference variable points to the other object, and the other variable still points to the previous object
var a = {age:12}
var b = a
a = {name:`sam`.age: 18}
console.log(b.age,a.name,a.age)//12 sam 18
function fn2(obj) {
obj = {age:15}
}
fn2(a)
console.log(a.age) / / 18
Copy the code
// Functions are also objects
var a = 3
function fn(b) {
b = b + 1
}
fn(a)
console.log(a)/ / 3
Copy the code
2 object
Object: multiple data encapsulation body, an object represents a thing in reality, attribute value is a function called method
Functions: a wrapper with a specific function that only functions can execute; Improved code reuse; Easy to read function declarations
test()
obj.test()
new test()
Test.call /apply(obj) // can be called by a function called a method that specifies any object
var obj = {}
function test2() {
this.xxx = 'july'
}
//obj.test2() cannot be called directly, and does not exist
test2.call(obj) // You can call a function called a method that specifies any object
console.log(obj.xxx)
Copy the code
(1) new
1 Create an object based on ctor. Prototype.
2 Execute the constructor and bind this to the newly created object.
3 Determine if the result of the constructor execution is a reference data type, if so, return the result of the constructor execution, otherwise return the created object.
function newOperator(ctor, ... args) {
if (typeofctor ! = ='function') {
throw new TypeError('Type Error');
}
const obj = Object.create(ctor.prototype);
const res = ctor.apply(obj, args);
const isObject = typeof res === 'object'&& res ! = =null;
const isFunction = typeof res === 'function';
return isObject || isFunction ? res : obj;
}
Copy the code
(2) Constructor creates object
(1) Create object with factory method:
This method allows you to create objects in large numbers, using Object constructors. Therefore, all the objects created are of the type Object, which makes it impossible to distinguish objects of different typesCopy the code
(2) So use the constructor to create an object:
The difference between a constructor and a normal function is how it is called. A normal function is called directly, whereas a constructor needs to be called using the new keyword. Objects created using the same constructor are called class objects. * The object we will create through a constructor is called an instance of this classCopy the code
-
Constructor execution flow:
* 1. Create a new object as soon as new appears * 2. Set the new object to this in the function, and use this to reference the new object * 3 in the constructor. Execute the code in the function line by line * 4. Return the new object as the return valueCopy the code
3 this
* The parser passes an implicit argument inside the function each time it calls it. The implicit argument is this. This refers to an object, which we call the context object of the function execution. When called as a function, this is always window *2. When called as a method, this is the object on which the method was called *3 When called as a constructor, this is the newly created object *4 When called using Call and apply, this is the object specifiedCopy the code
var name = 'global'
function fun() {
console.log(this.name)
}
var obj = {
name:'tom'.sayName:fun
}
var obj2 = {
name:'lily'.sayName:fun
}
// Depending on how the function is called, this refers to a different object
//1. When called as a function, this is always window
fun()/ / global;
//2. When called as a method, this is the object that calls the method
obj.sayName()//tom;
obj2.sayName()//lily
Copy the code
How to determine this:
test(): window
p.test(): p
New test(): Newly created object
p.call(obj): obj
Call () and apply() methods
function fun() {
alert(this.name)
}
var obj = {name:'obj'.sayName:function () {
alert(this.name)
}}
var obj2 = {name:'obj2'}
// fun.call(obj) //obj
// fun.apply(obj2.name)//obj2
// fun()//window
fun.call(obj,2.3)
fun.apply(obj,[2.3])
// obj.sayName.apply(obj2)
Copy the code
Prototype, prototype chain, inheritance
(1) Function prototype property
A prototype is an object, no different from any other object, that can be obtained through the constructor. Constructor. Prototype
/ / prototype prototype
console.log(Date.prototype, typeof Date.prototype)
function Fun() {}console.log(Fun.prototype)// The prototype Object, which by default points to an empty Object
Copy the code
// Add a method to the prototype object to use on the instance object
Fun.prototype.test = function () {
console.log('test()')}var fun = new Fun()
fun.test()
console.log(Fun.prototype)//{ test: [Function (anonymous)] }
console.log(Date.prototype.constructor === Date)//true
console.log(Fun.prototype.constructor === Fun)//true
Copy the code
// Explicit prototype (Funtion's prototype) and implicit prototype (fun's __proto__)
//1 defines the constructor
function Fn() {// internal statement: this.prototype={}
}
console.log(Fn.prototype)
// 2 Create an instance object
var fn = new Fn()// Internal statement: this.__proto__ = fn.prototype
console.log(fn.__proto__)
// The explicit stereotype of the corresponding constructor = the implicit stereotype of the object
console.log(Fn.prototype === fn.__proto__)//true, since they both hold the same address value
// 3 Add methods to the explicit prototype of the constructor
Fn.prototype.test = function () {
console.log('test()')}// 4 Invoke the prototype's methods through the instance
fn.test()
Copy the code
(2) Prototype chain (Implicit prototype chain)
- When accessing an object’s properties,
-
First look in their own properties, find the return
-
If not, look up the __proto__ chain and return
-
If not found, return undefined
Prototype Object and Object, so it also has a prototype, when we use an Object property or method, will now find itself, if there is, in itself is used directly, if not to the prototype Object to find, if there is one on the prototype Object, is used, if you don't have to prototype prototype, until you find the prototype of the Object, Object has no prototype. If no prototype is found in Object, undefined is returnedCopy the code
-
- Function: Find an object’s properties (methods)
A simpler approach is to use stereotypes to make one reference type inherit the properties and methods of another.
function MyClass() {
}
MyClass.prototype.name = 'I'm the name in the archetype.'
var mc = new MyClass()
mc.age = 12
console.log(mc.name)// I am the name in the prototype
console.log('name' in mc)//true
console.log(mc.hasOwnProperty('age'))//true
console.log(mc.hasOwnProperty('hasOwnProperty'))//false
console.log(mc.__proto__.hasOwnProperty('hasOwnProperty'))//false
console.log(mc.__proto__.__proto__.hasOwnProperty('hasOwnProperty'))//true
Copy the code
// Prototype chain: Essentially an implicit prototype chain
console.log(Object.prototype.__proto__)
function Fn() {
this.test1 = function () {
console.log('test1')
}
}
Fn.prototype.test2 = function () {
console.log('test2()')}var fn = new Fn()
fn.test1()
fn.test2()
console.log(fn.toString())
console.log(fn.test3)//undefined
//fn.test3()//TypeError: fn.test3 is not a function
Copy the code
// By default, the explicit prototype of the 1 function points to an empty instance of Object.
console.log(Fn.prototype instanceof Object)//true
console.log(Object.prototype instanceof Object)//false
console.log(Function.prototype instanceof Object)//true
// all functions are instances of Function (Function is also instance of Function)
console.log(Function.__proto__ === Function.prototype)
An Object is the end of the prototype chain
console.log(Object.prototype.__proto__)//null
Copy the code
/ / exercise 1
function Fn(){
}
Fn.prototype.a = 'xxx'
var fn1 = new Fn()
console.log(fn1.a)//xxx
var fn2 = new Fn()
fn2.a = 'yyy'
console.log(fn1.a,fn2.a)//xxx yyy
Copy the code
// Exercise 1.5 Note: Reading an object's property value looks for the prototype chain, but setting an object's property value does not look for the prototype chain
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.setName = function(name){
this.name = name
}
var p1 = new Person('tom'.12)
p1.setName('bob')
console.log(p1)//Person { name: 'bob', age: 12 }
var p2 = new Person('jack'.12)
p2.setName('lily')
console.log(p2)//Person { name: 'lily', age: 12 }
console.log(p1.__proto__ === p2.__proto__)//true
Copy the code
2 / / practice
Object.prototype.foo = 'Object'
Function.prototype.foo = 'Function'
function Animal() {}var cat = new Animal()
console.log(cat.foo)//Object
console.log(Animal.foo)//Function
Copy the code
/ / 3
var b ={x:4}
function fn2(o) {
this.x = o.x
}
fn2.prototype = {
init:function () {
return this.x
}
}
var fn3 = new fn2({x:5})
var c = fn3.init()
console.log(fn3.init.call(b))/ / 4
console.log(c)/ / 5
Copy the code
// A (instance object) instanceof B (constructor)
function Foo() {}
var f1 = new Foo()
console.log(f1 instanceof Foo)//true
console.log(f1 instanceof Object)//true
console.log(Object instanceof Function)//true
console.log(Object instanceof Object)//true
console.log(Function instanceof Function)//True
console.log(Function instanceof Object)//true
function Foo() {}
console.log(Object instanceof Foo)//false
Copy the code
/* Question 1 */
var A = function() {
}
A.prototype.n = 1
var b = new A()
//b That's it
A.prototype = {
n: 2.m: 3
}
var c = new A()
console.log(b.n, b.m, c.n, c.m)
// answer 1,undefined,2,3.
Copy the code
/* Question 2 */
var F = function(){};
Object.prototype.a = function(){
console.log('a()')};Function.prototype.b = function(){
console.log('b()')};var f = new F();
f.a() //a()
f.b()// error f.b is not a function
F.a()//a()
F.b()/ / (b)
Copy the code
(3) Prototype inheritance
/ / inheritance
class father {
constructor() {
this.name = 'jack'
this.age = 30
}
sayName(){
return this.name
}
static saySex(){
return 'male'}}class child extends father{
constructor() {
super(a);this.name = 'tony'
this.age =2
}
sayAge(){
console.log(this.age)//undefined}}let cc = new child()
let ff = new father()
console.log(cc.sayName())//tony
console.log(cc.sayAge())/ / 2
console.log(father.saySex()) //male
// console.log(cc.saySex())
// console.log(ff.saySex())
Copy the code
How do you implement the prototype chain when the Person class inherits
function Parent() {
this.name = 'parent';
}
function Child() {
Parent.call(this);
this.type = 'children';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Copy the code
5 Execution Context
(1) Variable promotion
var a = 3
function fn() {
console.log(a)//undefined
var a = 4
}
fn()
console.log(b)//undefined
fn2()// Can be called, function promotion
fn3()// uncallable, variable promoted
var b =3
function fn2() {
console.log('fn2()')//fn2()
}
var fn3 = function () {
console.log('fn3()')}Copy the code
(2) Global execution context
console.log(a1,window.a1)
window.a2()
console.log(this)
var a1 =2
function a2() {
console.log('a2()')}Copy the code
(3) Function execution context (N+1 principle)
// Function execution context (N+1 principle), is closed, virtual, and exists on the stack, only when the function body, the function execution context, but prepared in advance; The function is automatically released after the call
function fn(a1) {
console.log(a1)/ / 2
console.log(a2)//undefine
a3()//a3()
console.log(this)//window
console.log(arguments)// pseudo-array (2,3)
var a2 =3
function a3() {
console.log('a3()')
}
}
fn(2.3)
Copy the code
Execution order
// 1 To enter the window global execution context
var a = 10
var bar = function (x) {
var b = 5
foo(x+b)//3. Enter the execution context of foo
}
var foo = function (y) {
var c = 5
console.log(a+c+y)
}
bar(10)//2 Enter the bar function execution context
Copy the code
console.log('global'+i)//undefined
var i = 1
foo(1)
function foo(i){
if(i==4) {return
}
console.log('foo() begin'+i)/ / 1 2 3
foo(i+1)// Recursive call: calls itself from within a function
console.log('foo() end'+i)/ / 3 2 1
}
console.log('global'+i) / / 1
Copy the code
//test1: variable promotion, function promotion
function a() {}
var a
console.log(typeof a)//function
//test2
if(! (bin window)) {var b = 1
}
console.log(b)//undefined
//test3
var c= 1
function c(c) {
console.log(c)
}
c(2)// error: c is not a function, variable promoted
Copy the code
(4) Scope (N+1 principle) and scope chain
First, let’s warm up a few questions, make clear the global scope, function scope
var a = 123
function fun1() {
alert(a)/ / 123; Function scope does not have a, go to global scope to find a
}
fun1()
Copy the code
var b = 123
function fun2() {
alert(b) // undefined; So b in function scope is undefined of 2
var b = 456 Var b = 456 (1);
}
fun2()
alert(b) / / 123; So we're looking for b of 3 in global scope
Copy the code
var c = 123
function fun3() {
alert(c) / / 123; First of all, there's no C in the function scope, so look for c (1) in the global scope.
c = 456 // c is global, because there is no var, so window.c; So I'm going to reassign the global c 456 (2)
}
fun3()
alert(c)/ / 456; Because c reassigns 456 (3)
Copy the code
var d = 123
function fun4(d) {Var d (1); var d (1)
alert(d) // undefined; In the scope of this function, d is not currently assigned (2)
d = 456 // d = 456 (3)
}
fun4()
alert(d)/ / 123; This is d of 4 in global scope.
Copy the code
var e = 123
function fun5(e) {// First, the corporeal parameter e is relative to the function scope var e (1).
alert(e) / / 123; Var e = 123 (3)
e = 456 // The function e is 456 (4).
}
fun5(123)// Then, the argument 123, assign e = 123 (2)
alert(e) / / 123; This is e of 5 in global scope.
Copy the code
Scope is static, (global scope, function scope, block scope), used to isolate variables, different scope under the same gate variable does not conflict
var a = 10,
b = 20
function fn(x) {
var a = 100
c = 300
console.log('fn()',a,b,c,x)//fn() 100 20 300 10
function bar(x) {
var a = 1000,
d = 400
console.log('bar()',a,b,c,d,x)//bar() 1000 20 300 400 100 //bar() 1000 20 300 400 200
}
bar(100)
bar(200)
}
fn(10)
Copy the code
// Scope chain
var a = 1
function fn1() {
var b = 2
function fn2() {
var c = 3
console.log(c)/ / 3
console.log(b)/ / 2
console.log(a)/ / 1
//console.log(d)// Save, undefined
}
fn2()
}
fn1()
Copy the code
//test1
var x= 10
function fn() {
console.log(x)
}
function show(f) {
var x = 20
f()
}
show(fn)
var fn =function () {
console.log(fn)//[Function: fn]
}
fn()
Copy the code
//test2
var obj ={
fn2:function () {
console.log(fn2)/ / save
console.log(this.fn2)//[Function: fn2]
}
}
obj.fn2()
Copy the code
6 the closure
Closure: Function nesting, the inner function references the data of the outer function and executes the outer function
In plain English, function B inside function A creates a closure when it is referenced by a variable outside of function A.
When are closures used? The most common is when function encapsulation, and then when using timer, will often use…
function fn1() {
var a = 2
var b = 3
function fn2() {// Execute the function definition to generate the closure (without calling the inner function)
console.log(a)
}
}
fn1()// Execute external functions
Copy the code
(1) The application of closures
1 Takes a function as the return value of another function
function fn1() {
var a = 2Function definition execution and function execution are two different things (the internal function object has already been created due to function promotion).
function fn2() {// Create closure functions
a++
console.log(a)
}
return fn2
}
var f = fn1()
f()//3 Execute the function
f()/ / 4
f = null // Closure is dead, (function objects containing closures are called garbage objects)
Copy the code
Pass the function as an argument to another function call
function showDelay(meg,time) {
setTimeout(function () {
alert(msg)/ / closures
},time)
}
showDelay('july'.2000)
Copy the code
3. Define JS modules to encapsulate all functions together
function myModule() {
var msg ='July'
// The behavior of manipulating data
function doSomething() {
console.log('doSomething()'+msg.toUpperCase())
}
function doOtherthing() {
console.log('doOtherthing()'+msg.toLowerCase())
}
// Expose the object outwards
return {
doSomething:doSomething,
doOtherthing:doOtherthing
}
}
// Way2 is better and can be loaded directly on Windows. You can use it directly
(function (window) {
var msg = 'July'
// The behavior of manipulating data
function doSomething() {
console.log('doSomething()'+msg.toUpperCase())
}
function doOtherthing() {
console.log('doOtherthing()'+msg.toLowerCase())
}
// // Expose objects outwards
window.myModule2 = {
doSomething:doSomething,
doOtherthing:doOtherthing
}
})(window)
Copy the code
//test1
var name = 'the window'
var object = {
name:'my object'.getNameFunc:function () {
return function () {/ / no closure
return this.name }; }};console.log(object.getNameFunc()())//the window
Copy the code
//test2
var name2 = 'the window'
var object2 = {
name2:'my object'.getNameFunc:function () {
var that = this
return function () {/ / a closure
return that.name2
}
}
};
console.log(object2.getNameFunc()())//my object
Copy the code
//test3
function fun(n,o) {
console.log(o)
return{
fun:function (m) {
return fun(m,n)// Call fun(n,o), closure, use n, pass to o}}; }var a = fun(0); a.fun(1); a.fun(2); a.fun(3);/ / undefined, 0, 0
var b = fun(0).fun(1).fun(2).fun(3)/ / undefined, 0
var c = fun(0).fun(1); c.fun(2); c.fun(3)/ / undefined, 0,1,1
Copy the code
Let’s write a simple closure:
function a(){
var i=0;
function b(){
i++;
alert(i);
}
return b;
}
var c = a();
c();/ /?
c();/ /?
c();/ /? Interviewee: It should be one, two, three.
Copy the code
How it works: I is a variable in function A. Its value is changed in function B. Each time function B executes, the value of I is incremented by 1. Therefore, the I variable in function A will always be kept in memory. Closures are used when we need to define variables in a module that we want to keep in memory but not “contaminate” global variables.
Closures are useful for reading variables inside functions and for keeping their values in memory at all times.
// Create an array element
var num = new Array(a);for(var i=0; i<4; i++){
//num[I] = closure; // When the closure is called four times, four separate functions are generated
// Each function has its own personalization (difference) information that it can access
num[i] = f1(i);
}
function f1(n){
function f2(){
alert(n);
}
return f2;
}
num[2] ();/ / 2
num[1] ();/ / 1
num[0] ();/ / 0
num[3] ();/ / 3
Copy the code
(2) Advantages and disadvantages of closures:
Advantages:
① Reduce global variables; ② Reduce the number of parameters of transfer function; (3) encapsulation;Copy the code
Disadvantages:
(1) The use of closures will occupy memory resources, excessive use of closures will lead to memory overflow and other solutions: simple to say that those variables that are not needed, but the garbage collection can not collect those variables assigned to null, and let the garbage collection take away;Copy the code
7 Event loop mechanism
As javascript code executes, different variables are stored in different locations in memory: heap and stack. There are some objects in the heap. The stack holds some basic type variables and Pointers to objects.
When we call a method, JS generates an execution context corresponding to the method, also called the execution context. The execution environment contains the method’s private scope, the upper scope’s pointer, the method’s parameters, variables, and the scope’s this object.
When a series of methods are called in sequence, because JS is single-threaded, only one method can be executed at a time, so a series of methods are queued on the execution stack.
When a script is executed for the first time, the JS engine parses the code, adds the synchronized code to the stack in the order it is executed, and then executes it from scratch.
If a method is currently executing, js adds the method’s execution environment to the execution stack, and then enters the execution environment to continue executing the code. When the code in this execution environment completes and returns the result, js exits the execution environment and destroys the execution environment, returning to the execution environment of the previous method.
This process is repeated until all the code in the execution stack has been executed.
A method execution adds its execution environment to the execution stack, in which it can call other methods, or even itself, only to add another execution environment to the execution stack. This process can go on indefinitely, unless a stack overflow occurs. The above procedure is all about synchronous code execution.
When the JS engine encounters an asynchronous event, the JS will add the event to the event queue. Instead of executing its callback immediately, it waits for the current stack to complete, immediately processes events in the microtask queue, and then retrieves an event from the macro task queue.
The main thread takes the first event, puts the corresponding callback on the stack, executes the synchronized code, and so on, creating an infinite loop. This is why the process is called an Event Loop.
Macro task vs. Micro Task
Different asynchronous tasks are divided into two categories: micro tasks: new Promise() and macro tasks: setInterval(),setTimeout()
The following events are microtasks
new Promise(a)new MutaionObserver()
]
setTimeout(function () {
console.log(1);
});
new Promise(function(resolve,reject){
console.log(2)
resolve(3)
}).then(function(val){
console.log(val); }) results are:2
3
1
Copy the code