1 Event cycle mechanism

Because JS is single threaded, if two threads have conflicting operations on the DOM, to solve the blocking situation, so there is oneThe 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: macro task: whole code,setTimeout(), setInterval() ** and Micro Task: New Promise(). Then callback inside

Why you should distinguish between macro and micro tasks: Since all tasks are stored in an event queue and are first in first out, but some tasks have a high priority, the concept of micro tasks is introduced to ensure that tasks are completed in order. Js will first complete the macro task, then complete the task in the microtask queue.

  • Event loop in Node

Macro task execution sequence: 1 timer Timer: executes the scheduled setTimeout and setInterval callback functions. 2 Pending Callback: Idle,prepare: Only used internally 4 Poll: Retrieves new I/O events, executes I/O callbacks 5 Check: Executes setImmediate () callbacks 6 Close Callbacks socket.on(‘close’,()=>{})

  • The order in which microtasks and macro tasks are executed in node

Node v10 and before: 1 Performs all tasks in a phase. 2 Performs tasks in the nextTick queue. 3 Performs tasks in the microtask queue

//1 async1 function defined, but not called, so now not output
async function async1() {
  / / 6
  console.log('async1 start')
  / / 7
  await async2()Async2 () in new Promise(() =>{}), async2, print async2
  // then (); then (); // Then ();
  //13 The first microtask, print
  console.log('async1 end')}//2 async2 function defined, but not called, so now not output
async function async2() {
  console.log('async2')}/ / 3 print
console.log('script start')

// 4 setTimeout is a macro task whose priority is lower than that of the micro task. It will be moved to the next macro task queue
setTimeout(function () {
  / / 15 printing
  console.log('setTimeout')},0)

// 5 async1 is executed, so 'async1 start'
async1()

/ / 9
new Promise(function (resolve) {
  // 10 Synchronize code to print
  console.log('Promise1')
  //11. Then is asynchronous, is a microtask, is not executed first
  resolve()
}).then(function () {
  //14 The second microtask is printed. At this point, the microtask queue is cleared, and the next macro task, setTimeout, is enabled
  console.log('Promise2')})//12 Prints, at which point the first macro task has been executed and the microtask queue is cleared
console.log('script end')

/* Print order: script start async1 start async2 Promise1 script end async1 end Promise2 setTimeout */
Copy the code
/ / 1 print
console.log('start')

// 2 macro task, do not execute, move to the next round
//8 Execute the second macro task
setTimeout(() = >{
  / / 9 print
  console.log('children2')
  //10 Instead of adding the. Then callback directly to the microtask queue,
  Promise.resolve().then(() = >{
    / / 11 print
    console.log('children3')})},0)

/ / 3
new Promise(function (resolve, reject) {
  // 4 Synchronous, print
  console.log('children4')
  // 5 macro task, do not execute, move to the next round
  // 12 Perform the third macro task
  setTimeout(function () {
    / / print 13
    console.log('children5')
    Resolve resolve to change the state of the Promise to fullfilled
    resolve('children6')},0)
  //6 microtasks are not executed.
  SetTimeout is a macro task, so the callback is not added to the microtask queue
  
}).then((res) = >{
  / / 14 to print
  console.log('children7')
  // 15 Macro task execution
  setTimeout(() = >{
    / / 17 print
    console.log(res)
  },0)})/* * start * children4 * the first macro task is finished, then the children4 queue is emptied, but no children2 * the second macro task is finished, then the children4 queue is emptied, * children3 * Tries to execute the third macro task * children5 * children7 * children6 * */
Copy the code
const p = function () {
  / / 1 macro task
  return new Promise((resolve, reject) = > {
    // 2 macro task
    const p1 = new Promise((resolve, reject) = > {
      setTimeout(() = >{
        resolve(1)},0)
      resolve(2)})// 3 Put it into the microtask queue
    p1.then((res) = >{
      console.log(res)/ / 2
    })
    / / 4 printing
    console.log(3)
    resolve(4)})}// add 5 to the microtask queue
p().then((res) = >{
  console.log(res)/ / 4
})
/ / 4 printing
console.log('end')

/*
*3
* end
* 2
* 4
* */
Copy the code

2 Event capture and bubbling (Application Scenario: Event Delegate)

Capture: top down, Window -> Target element bubble: bottom up, target element -> Window

  • Window.addeventlistener listens for what phase of events?

Bubbling phase

window.addEventListener('click'.() = >{})// The third argument is false by default
Copy the code

Capture phase

window.addEventListener('click'.() = >{},true)
Copy the code
  • Example: On the history screen, add an attribute, banner = true, that no longer responds to the principle function, prompting alter

Solution: Bind a capture event at the top level to block bubbling,

window.addEventListener('click'.() = >{
  if(banned){
    e.stopPropagation()// Block capture}},true)
Copy the code
  • Application scenario: Event delegation
<! doctypehtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
</head>
<body>
<ul id="ul">
  <li>1</li>
  <li>1</li>
  <li>1</li>
  <li>1</li>
  <li>1</li>
  <li>1</li>
</ul>
</body>
<script type="text/javascript">

 const ul = document.querySelector('ul')
  ul.addEventListener('click'.function (e) {
    const target = e.target
    if (target.tagName.toLowerCase() === 'li') {
      const liList = this.querySelectorAll('li')
      const index = Array.prototype.indexOf.call(liList,target)
      alert(` content is${target.innerHTML}Index,${index}`)}})</script>
</html>
Copy the code

3 Throttling, anti-shake

  • Function throttling: Sets a time interval to execute if a frequently triggered event occurs longer than that interval, otherwise not. (Applied to resize, Scorll events)

Is to ensure that the function is executed at most once at a given time.

  • The timestamp is executed immediately for the first time
function throttle(callback,wait) {
  // Define the start time
  let start = 0
// Return result is a function
  return function (e) {
    // Determine the interval and get the current timestamp
    let now = Date.now()
    / / determine
    if (now - start >= wait) {
      // If the judgment is met, the callback function is executed
      callback.call(this,e)// This points back to the event source
      // Change the start time
      start = now
    }
  }
}
Copy the code
  • The first (last) execution is not immediate
function throttle(fn,interval){
    let timer = null
    return funtion(){
        let context = this
        if(! timer){ timer = SetTimeout(funtion(){
                fn.apply(context,arguments)// Arguments here refer to arguments passed in
                timer = null
            },interval)
        }
    }
}
Copy the code
  • The first execution is not immediately executed, and the last execution is immediately executed
funtion throttle(fn,delay){
    let timer = null
    let start = Date.now()
    
    return funtion(){
        let curTime = Date.now()
        let remainTime = delay - (cutTime - start)// Remaining time = full interval time - time that has passed
        let context = this
        cleanTimeout(timer)// Make sure that every time you enter, you recalculate remainTime
        if(remainTime <= 0){
            fn.apply(context,arguments)
            start = Date.now()
        }else{
            timer = setTimeout(fn,remainTime)
        }
    }
}
Copy the code
<! doctypehtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script type="text/javascript" src="./ function throttle.js"></script>
  <style>
  body{
    height: 2000px;
    background: linear-gradient(paleturquoise,pink);
  }
  </style>
</head>
<body>
  <script type="text/javascript">
    // Bind the scroll event

    window.addEventListener('scroll',throttle(function (e) {
      // console.log(Date.now())
      console.log(e)
    },500))

  </script>
</body>
</html>
Copy the code

  • Function stabilization: an event is executed if it has not been triggered again for a period of time. If it triggers again, wait a little longer. (Apply the input keyword to search for events)

A function is executed after it is not called again for a specified period of time.

function debounce(callback,time) {
  // Timer variable
  let timeId = null
  // Return a function
  return function (e) {
    / / determine
    if(timeId ! = =null) {
      // Empty the timer
      clearTimeout(timeId)
    }
    // Start timer
    timeId = setTimeout(() = >{
      // Perform the callback
      callback.call(this,e)// This is the outer this of the callback
    },time)
  }
}
Copy the code
<! doctypehtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script type="text/javascript" src="./ function buffer.js"></script>
</head>
<body>
<input type="text">
<script type="text/javascript">
  let input = document.querySelector('input')
  // input.onkeydown = function (e) {
  // console.log(e.keyCode)
  // }
  input.onkeydown = debounce( function (e) {
    console.log(e.keyCode)
  },500)
</script>
</body>
</html>
Copy the code

4 Promise

When the promise is instantiated, it is executed. .then or await is to get the value

/ / Promise
new Promise((resolve, reject) = > {
  console.log('1')

  setTimeout(() = >{
    resolve('2')},1000)

}).then(res= > {
  console.log(res)

  return new Promise((resolve,reject) = >{
      setTimeout(() = >{
        resolve( {msg:'3'})},1000)})},err= >{
  console.log(err)
}).then(res= >{
  console.log(res.msg)
  }
)
Copy the code
  • Static method: promise.all () promise.race () promise.resolve () promise.reject ()
  • (1) Promise. Resolve ()
static resolve(value) {
  if (value instanceof Promise) {
    // If it is a Promise instance, return it directly
    return value;
  } else {
    // If it is not a Promise instance, return a new Promise object, which is FULFILLED
    return new Promise((resolve, reject) = >resolve(value)); }}Copy the code
  • (2) the Promise. Reject ()
static reject(reason) {
  return new Promise((resolve, reject) = >{ reject(reason); })}Copy the code
  • (3) the promiss. All

Promise.all supports chained calls, essentially returning a Promise instance that changes its state through resolve and reject.

Promise.all can wrap multiple Promise instances into a new Promise instance. Also, success and failure return different values, with success returning an array of results and failure returning the first rejected state.

Return a promise object. The returned promise state is successful only if all promises are successful. This is a big pity, which will be FULFILLED gradually. This is a big pity, which is gradually forgotten. 3 The array members are not necessarily promises, so use promise.resolve ().Copy the code
function PromiseAll(promiseArray) {
  return new Promise((resolve, reject) = > {
    // Check whether the argument passed is []
    if (!Array.isArray(promiseArray)) {
      return reject(new Error('You have to pass in an array.'))}const res = []
    const len = promiseArray.length
    / / counter
    let counter = 0
    for (let i = 0; i < len.length; i++) {
      Promise.resolve(promiseArray[i]).then(value= > {
        counter++
        res[i] = value
        // The state of the return promise can be changed if all execution is completed
        if (counter === len) {
          resolve(res)
        }
      }).catch(err= >reject(err))
    }
  })
}


/ / test
const p1 = new Promise((res,rej) = >{
  setTimeout(() = >{
    res('1')},1000)})const p2 = new Promise((res,rej) = >{
  setTimeout(() = >{
    res('2')},2000)})const p3 = new Promise((res,rej) = >{
  setTimeout(() = >{
    res('3')},3000)})const proAll = PromiseAll([p1,p2,p3])
  .then(res= >
    console.log(res)
  )
  .catch((err) = >
    console.log(err)
  )
Copy the code
  • (4) promiss. Race

Promse.race is a race, which means that a Promise. Race ([P1, P2, P3]) returns the fastest result, regardless of whether the result itself is a success or a failure.

Promise.race = function(promiseArr) {
  return new Promise((resolve, reject) = > {
    promiseArr.forEach(p= > {
      // If it is not a Promise instance, it needs to be converted to a Promise instance
      Promise.resolve(p).then(
        val= > resolve(val),
        err= > reject(err),
      )
    })
  })
}
Copy the code
  • A decorator

Call a request (constant), multiple places will request it, but without global state management, you can use Promise,

const cacheMap = new Map() function enableCache(target,name,describe) { const cal = describe.value describe.value = async function (... args) { const cacheKey = name + JSON.stringify(args) if (! cacheKey.get(cacheKey)) { const cacheValue = Promise.resolve(val.apply(this.args)).catch(_=>{ cacheMap.set(cacheKey,null) }) cacheMap.set(cacheKey,cacheValue) } return cacheMap.get(cacheKey) } return describe } class PromiseClass { @enableCache static async getInfo(){ } } PromiseClass.getInfo() PromiseClass.getInfo() PromiseClass.getInfo() PromiseClass.getInfo()Copy the code

5 Front-end loading optimization and concurrent processing

Performance test page: developers.google.com/speed/pages… Polyfill: Polyfill. IO/v3 / url – buil… (This CDN loads Polyfill on demand and reduces volume)

  • An important point of optimization: first screen time (vUE white screen time)

Reduce page loading time => Reduce page loading resources:

  • 1 Request the required resource:
    • Asynchronous loading, image lazy loading (lazy loading), polyfill (ES high version to low version of ES, for version adaptation),

Lazy loading of pictures: Observe.observe (DOM node)// The image is not loaded, Observer. unobserve(DOM node)// If the image is loaded, cancel the observation

// Get the image label
const imgs = document.querySelectorAll('img')


const observer = new IntersectionObserver(callback )// The callback function fires twice: 1 sees the trigger and 2 does not see the trigger

// Incoming entries are arrays
const callback = entries= > {
 entries.forEach( entry= >{
   if (entry.isIntersecting) {//isIntersecting can determine whether the image has been observed when the callback function is triggered this time. If it is true, the image has been observed
     const img = entry.target
     // Get the custom HTML attribute data-src
     const data_src = img.getAttribute('data-src')
     img.setAttribute('src',data_src)// Assign the original img SRC attribute to data_src
     observer.unobserve(img)// When the image is loaded, cancel the observation
   }
 })
}

imgs.forEach(img= >{
 observer.observe(img)
})
Copy the code
  • 2 Reduce the resource volume
    • Package compression such as Webpack,

    • Compress the size of cookies as much as possible (the user login state should be preserved, and the other ones can be compressed)

    • Gizp (compress static JS CSS and other resources algorithm),

    • Image format optimization, compression (Tinypng.com, can compress 80%), WebP image format (first to determine whether the browser supports WebP, before converting the image to WebP)

    Ali cloud OSS support spelling parameters, image format to webP, need to pay attention to what?

// Determine compatibility
function checkwebp() {
 try{
   return(
     document.createElement('canvas')// Create a Canvas element and convert the image to base64. The beginning of Base63 carries the image format
       .toDataURL('img/webp')// Here we try to convert the image format to webP
       .indexOf('data:image/webp') = = =0 // If you start with 'data:image/webp', webp is supported)}catch (e) {
   return false}}const supportWebp = checkwebp()
// Next is the concatenation of strings, but the boundary conditions need to be considered carefully,
export function getWebpImageUrl(url) {
 if(! url) {throw Error('URL cannot be empty')}// Determine if it is base64, if it starts with 'date', return
 if (url.startsWith('date')) {
   return url
 }
 if(! supportWebp) {return url
 }
 // Next is the concatenation of strings
 return url + '? x-oss-processxxxx'
}
Copy the code
  • 3 timing optimization (optimize resources through some logical design)

    • Promise. All in js makes requests in parallel
    • SSR, can do cache, render the resources well, package, cached in the CSN file (), seo
    • prefetch ,prerender,preload
     <link rel='dns-prefetch' href='xxxx.com'< span style = "box-sizing: border-box! Important'preconnect' href='xxxx.com'< span style = "max-width: 100%; clear: both; min-height: 1em'preload' as='image' href='xxxx.com/p.png'Word-wrap: break-word! Important;"Copy the code
  • 4 Use caching wisely
    • CDN: CDN warm-up (CDN supplier distributes information to nodules in advance) CDN refresh (forced refresh)

    • If the execution time of a js is very long, how to analyze which function (decorator method to calculate the execution time of the function)

export function measure(target:any,name:string,descriptor:any){
 const oldValue = descriptor.value
 
 descriptor.value = async function () {
   console.time(name)
   const ret = await oldValue.apply(this.arguments);
   console.timeEnd(name)
   return  ret
 }
 return descriptor
}
Copy the code
  • Page has a huge amount of pictures, in addition to lazy loading, there is no limit to the loading of pictures

(Control concurrency limit via promise: promise.race + P.teng chain call to ensure sequential push)

function limitLoad(urls,handler,limit) {
  const sequence = [].concat(urls)// Copy the original array
  let promises = []
  // Take the first few URL elements and change the original array, i.e. the original array removes these elements
  promises = sequence.splice(0,limit).map((url,index) = >{
    // The map function converts the original URL to another format
    return  handler(url).then(() = >{
      return index
    })
  })
  // Race through promise.race to find the url that executes the fastest
  let p = Promise.race(promises)
  for (let i = 0; i <sequence.length ; i++) {
    // To ensure sequential push through the p.tenn chain call, where res is the index to find the fastest url to complete execution
    p = p.then((res) = >{
      // Reassign index and race again
      promises[res] = handler(sequence[i]).then(() = >{
        return res
      })
      return Promise.race(promises)
    })
  }
}

const urls = []

/ / test
function loadImg(url) {
  return new Promise((resolve, reject) = > {
    console.log(The '-'+url.info + 'start')
    setTimeout(() = >{
      console.log(url.info +'ok~')
      resolve()
    },url.time)
  })
}
limitLoad(urls,loadImg,3)// The incoming concurrency is 3
Copy the code

1 Data type & judgment method

  1. 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)
  1. 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

  1. 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
  1. 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, exist and stack, only the execution of the function body, 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 to 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