scope

A scope is the scope within which a variable is legally used. It can be divided into:

  1. Global scope
  2. Function scope
  3. Block-level scope

Variable ascension

Before a JS script (a

Function declarations take precedence over variable declarations.

Free variables

  1. A variable is not defined in the current scope, but is used
  2. They’ll go up to the top until they find it
  3. If the global scope is not found, XXX is not defined

These layers of relationships are called scope chains.

All free variables should be found in the function definition, in the parent scope, not in the execution place.

this

thisIt’s who executes you

This is part of the execution context, and the value of this is determined at function execution time, not function definition time.

var cyName = 'window-cy'
var obj = {
  cyName: 'obj-cy',
  printName: function(from){
    console.log(from + ': ' + this.cyName)
  }
}
obj.printName('obj') // obj-cy
obj.printName.call({cyName: 'call-cy'},'call') // call-cy
var p = obj.printName
p('window') // window-cy
Copy the code

Var cyName = ‘window-cy’ if let cyName = ‘window-cy’, p(‘window’) will print undefined. Since p(‘window’) this is window, var declarations are automatically mounted to window, but let is not.

thisUsage scenarios of

  1. Execute as a normal function
  2. Execute as an object property
  3. Execute as a constructor
  4. Arrow function
  5. usecall apply bindcall

closure

Closures are functions that refer to variables in the scope of another function.

Closure usage scenarios

  1. Function is returned as the return value
  2. Functions are passed as arguments
function F1() {
    var a = 100
    return function () {
        console.log(a) // 100
    }
}
var f1 = F1()
var a = 200
f1()
Copy the code
function F1() { var a = 100 return function () { console.log(a) // 100 } } function F2(f1) { var a = 200 f1() } var f1 =  F1() F2(f1)Copy the code

Application scenarios for closures in real development

  1. Hide data and only provide apis to the outside world
  2. Implement debounce and throttle control
function createCache(){
  const prefix = 'portal-'
  const data = {}
  return {
    set: function(key,value){
      data[prefix + key] = value
    },
    get: function(key){
      return data[prefix + key]
    }
  }
}
const c = createCache()
c.set('name','cy')
cy.get('name')
Copy the code

Related topics

var a = 10; function b() { a = 100; } b(); console.log(a); / / 100Copy the code
Var a = 10; function b() { a = 100; return; Function a() {} function a() {} function a() {} function b (funciton a); The next modification is the local variable A of function B, independent of a in the outer scope. } b(); console.log(a); / / 10Copy the code
var a = 10; if(true) { var a = 100; // var declares variables without block-level scope} console.log(a); / / 100Copy the code
var name = 'map'; function func() { console.log(this.name); // map } var object = { name: 'object', getNameFunc: function(fn) { fn && fn(); Return () => {return this.name; } // Arrow function this refers to the parent scope, so this is object}}; console.log(object.getNameFunc(func)()); // object // Result output // map // objectCopy the code

handwrittencall apply bindfunction

Feature implementations that use functions called as object properties

var cyName = 'window-cy' var obj = { cyName: 'obj-cy', printName: function (from) { console.log(from + ': ' + this.cyName) } } obj.printName.call({ cyName: 'call - cy'}, 'call'). The Function prototype. CyCall = Function (o) {const symbol = symbol () o (symbol) = this / / who call cyCall, Who is this / / to take the first parameters outside the let the args = Array. The prototype. Slice. The call (1) the arguments, / / arguments is an Array (containing the length attribute object), Typeof arguments is object. Array. The prototype. Slice. The call can put the class into an Array Array (symbol) (o... args) delete o[symbol] } obj.printName.cyCall({ cyName: 'cyCall-cy' }, 'cyCall') Function.prototype.cyApply = function (o) { const symbol = Symbol() o[symbol] = this const args = Array.prototype.slice.call(arguments, 1) o[symbol](... args.flat()) delete o[symbol] } obj.printName.cyApply({ cyName: 'cyApply-cy' }, ['cyApply']) Function.prototype.cyBind = function (o, ... args) { return (... innerArgs) => { const symbol = Symbol() o[symbol] = this o[symbol](... args, ... innerArgs) delete o[symbol] } } obj.printName.cyBind({ cyName: 'cyBind-cy' }, 'cyBind')()Copy the code