this/call/apply/bind (ten thousand words)

Keywords: Javascript Vue Attribute css3

preface

Hello, everyone. I'm zha'er πŸ‘¦ Every day πŸ’ͺ , you can get a promotion and a raise πŸ’° When general manager becomes CEO, marry Bai Fumei and go to the top of life πŸ—» I'm a little excited 😎.

This is my 13th issue A kind of , hope to be able to explain every knowledge point clearly, (of course, if you don't know which one, you can discuss it in the comment area!) A kind of , time starts!

If you find this article helpful, please like, collect, comment and leave your footprints of learning πŸ‘£ , I would like to talk about πŸ˜ƒ

Don't say much, start learning!!!

I will constantly revise the content of this article. Let's discuss it together! 😁

Learning css layout 🀣

Display attribute is the most important attribute used to control layout in css. Each element has a default display value, which is related to the type of element. The default value of most elements is generally block or inline.

  • Each element has a default display

Block elements are called block level elements; inline elements are called inline elements

The commonly used display value, sometimes none, is used to hide or display without deleting elements, display:none .

display set to none does not occupy the space it should be displayed; use v isibility:hidden It will take up space, but it's hidden. The element is still there.

Position attribute: static is the default value, pithy formula, and the child is the absolute parent. Fixed, a fixed positioning element will be positioned relative to the window, even if the page scrolls, it will stay in the same position.

Float in the css attribute, float can achieve the effect of text surrounding the picture:

img {
    float: right;
    margin: 0 0 1em 1em;
}

The clear attribute can be used for controlled floating elements. If a box has a float: left float added, you can use clear: left to clear the left float of the element.

Clear float, clearfix hack, you can use the new css Style:

.clearfix {
    overflow: auto;
}

Percentage width, which is a unit of measure relative to the containing block.

.clearfix {
    float: right;
    width: 50%;
}

nav {
  float: left;
  width: 15%;
}

section {
  margin-left: 15%;
}

Responsive design is a strategy that allows websites to "present" different display effects for different browsers and devices. It can make websites present good effects in different situations.

Inline block is an inline block label

.box {
  float: left;
  width: 200px;
  height: 100px;
  margin: 1em;
}
.after-box {
  clear: left;
}

// Same effect
.box1 {
  display: inline-block;
  width: 200px;
  height: 100px;
  margin: 1em;
}

flexbox is a new layout mode of css3, which is used to meet the complex needs of modern web.

<div class="flex-container">
    <div class="flex-item">flex item 1</div>
    <div class="flex-item">flex item 2</div>
</div>

.flex-container {
    display: -webkit-flex;
    display: flex;
    width: 300px;
    height: 240px;
    background-color: Silver;
}

.flex-item {
    background-color: DeepSkyBlue;
    width: 100px;
    height: 100px;
    margin: 5px;
}

JavaScript variables 😊

1, Int integer
2. Float
3. Boolean
4. String string
5. Array
6. Object object
7. Function function
8. Regular Expression

Hump nomenclature πŸ˜€

  • All lowercase, words separated by underscores
  • Mixed case, large hump, each word is capitalized, small hump, the first word is lowercase, the other is capitalized.

rule 😁

First character, English letter or underline; composition, English letter, number, underline; (disable, JavaScript keywords and reserved words)

statement πŸ˜ƒ

Display declaration, use var variable name, ({no type, repeated declaration, implicit declaration, direct copy without declaration}), ({declaration first, read-write later, assignment first, operation second}).

Variable type πŸ˜ƒ

The value type, which occupies a fixed space, is saved in the stack. What is saved and copied is the value itself. Use typeof to detect the type of data. The basic type of data is the value type.

The reference type is not fixed. It is saved in the heap. What is saved and copied is a pointer to the object. The instanceof is used to detect the data type. The object constructed by the new() method is a reference type.

Scope πŸ˜„

Global variables, including variables defined outside the function, var free variables defined inside the function; call, anywhere.

Local variables, including variables declared with var inside the function, parameter variables of the function; call, inside the current function body.

Priority: the local variable is higher than the global variable with the same name, the parameter variable is higher than the global variable with the same name, and the local variable is higher than the parameter variable with the same name.

Property: ignore the block level scope. The global variable is the attribute of the global object and the local variable is the attribute of the calling object.

Scope chain, inner function can access outer function local variables, outer function can not access inner function local variables.

Declaration cycle: global variables, except for being deleted, are always, local variables, and are declared until the function runs or is deleted. Recycling mechanism, clear marking, reference counting.

Logical operators πŸ˜…

! Logical non

Return true

Empty string
0
null
NaN
undefined

Return false

object
 Non empty string
 Non-zero value (Infinity)

Note: it is not logical and can be used twice in a row to convert any type to Boolean value

&&Logic and πŸ˜†

  • Returns the second operand when the first operand is an object
  • Returns the object when the second operand is an object and the first operand is true
  • Both operands are objects, return the second operand
  1. Returns null when an operand is null
  2. When an operand is NaN, NaN is returned
  3. An operand is undefined, and undefined is returned

Note: when the value of the first operand is false, the second operand is not evaluated.

Logical or|| πŸ˜‰

  • The first operand is an object and returns the first operand
  • The first operand is false, and the second operand is returned
  • Both operands are objects, return the first operand
  • Both operands are null, return null
  • Both operands are NaN, return NaN
  • Both operands are undefined, and undefined is returned

Note: if the first operand value is true, the second operand is not evaluated.

JavaScript array

add to

push() adds an array at the end of the array
unshift() adds elements to the array header
concat() merges two arrays

delete

pop() deletes and returns the last element of the value
shift() deletes and returns the first element of the array

Queue method (FIFO); stack method (LIFO).

splice() and slice()

splice()

  • Delete any number of items: 1. The starting subscript to be deleted; 2. The number of items to be deleted
  • Inserts the specified item at the specified location: 1, start subscript, 2, 0 (no item is deleted), 3, item to insert.
  • Replace any number of items: 1, start subscript, 2, number of items to delete, 3, items to insert

splice() method, annotation, which changes the original array. Used to add or remove elements from an array.

arrayObject.splice(index,howmany,item1,.....,itemX)

var arr = ['a', 'b', 'c']

arr.splice(2,1) // Delete an array of deleted elements

['c']

arr.splice(2,0) // Delete 0, return empty array

[]

var array = [1,2,3,4,5];
array.splice(3,2);
console.log(array);
// Results: [1,2,3]

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(2);
// Delete all elements starting at 2
// Myfish after operation: ["angel", "cloud"]
// Deleted element: ["mandarin", "sturgeon"]

All major browsers support splice()

Array array's splice() method, which is used to delete, insert and replace

Insert usage

Syntax: array.splice(starti,0, value 1, value 2...);

//Indicates where to insert, 0 indicates to delete 0 elements, because the insertion and replacement are expanded by the deletion function, with values of 1, 2 and the value to be inserted

var array = [1,2,3,4,5];
array.splice(2,0,11,22);

//Results: [1,2,11,22,3,4,5]

Use of substitution

grammar:array.splice(starti,n,Value 1, value 2);

var array = [1,2,3,4,5];
array.splice(2,2,11,22);

// Results: [1,2,11,22,5]

slice() function, select some elements from the existing array to form a new array

  1. Returns the starting position of an item
  2. Returns the end of an item

If it is a negative number, the array length plus the value is used to determine the position. The revelation position is actually the actual subscript of the array, and the actual subscript of the end position is the end value minus 1.

Array.prototype.slice()

The slice() method returns a new array object. The original array will not be changed. This object is a shallow copy of the original array determined by begin and end.

const animals = ['1', '2', '3', '4', '5'];

console.log(animals.slice(2));
// expected output: Array ["3", "4", "5"]

console.log(animals.slice(2, 4));
// expected output: Array ["3", "4"]

console.log(animals.slice(1, 5));
// expected output: Array ["1", "2", "3", "4"]

slice(start,end), which is intercepted from start to end. The return value is the collection of intercepted elements (only a new array is returned if the elements in the original array are copied shallowly)

var fruits = ['a', 'b', 'c', 'd', 'e'];
var citrus = fruits.slice(1, 3);

// fruits contains ['a', 'b', 'c', 'd', 'e']
// citrus contains ['b','c']

slice method uses a class array object / collection to convert it into a new array.

function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

In JavaScript, almost everything is an object, except for immutable primitive values like string, number, and Boolean.

Array.prototype.slice

function myFunc() {
    // Error, arguments is a class array object, not a real array
    arguments.sort();
    // Using slice, a method in Array prototype
    // It accepts an array like object( key:value)
    // And return a real array
    var args = Array.prototype.slice.call(arguments);
    // args is now a real Array, so you can use the sort() method of Array
    args.sort();
}

Array sorting, reverse() reverses the order of the elements in the array, and sort() sorts the character array or the number array.

function compare(value1, value2) {
    if(value1 < value2) {
        return -1;
    }else if(value1 > value2) {
        return 1;
    }else{
        return 0;
    }
}

Array conversion

  • toString() is converted to a string and returns
  • toLocaleString() is converted to a local format string and returns
  • join() splits the array with the specified separator and converts it to a string

The toString() function is used to return the string form of the current Object. This method belongs to an Object object Object.

Iteration method: parameters

  • every returns true if the function returns true for each item
  • filter returns all array members with a value of true
  • forEach no return value
  • map returns the result array of each function call
  • some returns true if any item returns true

Receive parameters:

  1. Functions to run on each item
  2. Scope object to run the function

Incoming parameters:

  1. Value item of array item
  2. The position index of the item in the array
  3. Array object itself array

Reduction method:

  • reduce traverses from the beginning of the array
  • reduceRight traverses from the end of the array

The reduce() method takes a function as an accumulator, and each value in the array (from left to right) starts to be reduced and finally evaluates to a value.

reduce() can be used as a higher-order function for the function's compose.

Note: reduce() does not perform a callback function for an empty array.

var numbers = [1, 2, 3, 4];
numbers.reduce(Callback function);
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
//  10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
//  15

var arr = [1,2,3,4];
// Summation
var sum = arr.reduce((x,y)=>x+y)
var sum1 = arr.reduce((x,y)=>x*y)

Find the maximum value of an array item

var max = arr.reduce(function (prev, cur) {
    return Math.max(prev,cur);
});

Take the maximum of two values and continue to the next round of adjustment.

Array de duplication

arr.reduce(function(prev,cur,index,arr){
...
}, init);

arr Represents the original array;
prev Represents the return value, or initial value, of the last callback call init;
cur Represents the array element currently being processed;
index Indicates the index of the array element currently being processed, if provided init Value, the index is 0; otherwise, the index is 1;
init Represents the initial value.

arr.reduce(callback,[initialValue])
initialValue (As first call callback The first parameter of.)

If this array is empty, what is the case with reduce?

var  arr = [];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
})
//"TypeError: Reduce of empty array with no initial value"

var  arr = [];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
},0)
console.log(arr, sum); // [] 0

in js, it is generally used to traverse objects and arrays

In function, judge whether the attribute exists in the object, in true, not in false.

in function, judge array, index number is property.

For an array, the elements of the array are recycled; for an object, the attributes of the object are recycled; for an object, the variables refer to the indexes of the array; for an object, the variables refer to the attributes of the object.

Count the number of occurrences of each element in the array

// Total score
var scoreReport = [
 {
   name: 'dada',
   score: 100
 },
 {
     name: 'Nezha the devil',
     score: 99
 }
]

// for
var sum = 0
for(var i = 0; i<scoreReport.length; i++) {
    sum += scoreReport[i].score
}

If you use reduce

var sum = scoreReport.reduce(function(prev, cur) {
    return cur.score + prev
},0);

Vuex

Rules in Vuex can only modify data in state in transitions, and actions cannot directly modify state

establish Vuex.Store Save the instance to the variable store, and export the store using export default

import Vuex from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
    
})
export default store

state

Frequently written documents store.js

import Vue from 'vue'
import Vuex from 'vuex'
// import * as getters from './getters'
Vue.use(Vuex)
const state = {
    // Place initial state
    a: 123
};

const mutations = {
    // Place our state change function
};

export default new Vuex.Store({
    state,
    mutations,
    // getters
})

this.$store.stateTo get the defined data

import Vuex from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
    state: {
        count: 1
    }
})
export default store
import Vuex from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
    state: {
        count: 1
    },
    getters: {
        // getters are equivalent to the computed calculation attribute in vue
        getStateCount: function(state){
            return state.count+1;
        }
    }
})
export default store

To modify the value in state, you need to submit the mutation to modify it

The getter in Vuex is just like the calculation property. The return value of getter will be cached according to its dependency, and will be recalculated only when its dependency value changes.

Getter accepts state as its first parameter:

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

When the getter is accessed through properties, it is cached as part of Vue's responsive system
When the getter is accessed through a method, it will be called every time without caching the result.

In a function{
    this.$store.commit('add');
}

import Vuex from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
    state: {
        count: 1
    },
    getters: {
        // getters are equivalent to the computed calculation attribute in vue
        getStateCount: function(state){
            return state.count+1;
        }
    },
    mutations: {
        add(state) {
            state.count += 1;
        },
    }
})
export default store

// xxx.vue
{{$store.getters.getStateCount}}

Submission - object style submission method, directly using the object containing the type attribute:

store.commit({
  type: 'increment',
  amount: 10
})

There is also an action in Vuex. This purpose is not to directly modify the value in the store as above, but to modify the status value by submitting an action, and then submitting the states in actions.

Define the functions for actions to submit the transitions first

Example:

In a function{
    this.$store.dispatch('addFun')
}

import Vuex from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
    state: {
        count: 1
    },
    getters: {
        // getters are equivalent to the computed calculation attribute in vue
        getStateCount: function(state){
            return state.count+1;
        }
    },
    mutations: {
        add(state) {
            state.count += 1;
        },
    },
    actions: {
    // Register actions, equivalent to methods in vue
        addFun(context){
            // Context receives a context object with properties of the same method as the store instance
            context.commit('add')
        },
    }
})
export default store

Use mapState, mapGetters, mapActions instead of this$ store.state.count And this$ store.dispatch ('addfun ') this way of writing.

How to use:

import {mapState, mapGetters, mapActions} from 'vuex';

// Using computed state changes

computed: {
    ...mapState({
        countdada: state=>state.count
    })
}

// Map getter s in the store to local calculation properties:
import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // Using object expansion operator to mix getter into computed object
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

...mapGetters({
  // Put` this.doneCount `Map to ` this$ store.getters.doneTodosCount `
  doneCount: 'doneTodosCount'
})

this in JavaScript

This, what is it? This, this keyword is executed as ThisBinding of the current execution environment.

In most cases, the way the function is called determines the value of this. This point is determined at call time, not at creation time.

// this points to global variables
function dadaqianduan() {
    return this;
}

console.log(dadaqianduan() === window); // true

Use call(), apply(), this to point to the bound object.

var person = {
    name: 'dada',
    age: 12
};
function sayHello(job) {
    console.log(this.name + "," + this.age + "," + job);
}

sayHello.call(person, 'it'); // dada,12,it
sayHello.apply(person, ['it']);

Arrow function, all arrow functions do not have their own this, and point to the outer layer. The arrow function captures the this value of its context as its own. (inside the function, the value of this depends on how the function is called.)

this of the arrow function always points to the object at the time of definition. Is not the object that the runtime is on.

function da() {
    setTimeout(()=>{
        console.log('this',this.id)
    },1000);
}

da.call({id: 12});

Arrow function is located in da function. Only after da function runs, it will be generated according to the definition. so, the object where da runs is exactly the object where arrow function is defined.

(a word worth exploring), using this in the arrow function is like using ordinary variables. If you can't find it in the scope of the arrow function, you will always look for the parent scope.

this also points to global variables, as follows:

var name = 'da';
var person = {
    name: 'dadaqianduan',
    getName: function() {
        return this.name;
    }
}
var getName = person.getName();
console.log(getName()); // da

As a constructor, this is bound to the new object being constructed.

function Person(name) {
    this.name = name;
    this.age = 12;
    this.say = function() {
        console.log(this.name + ":" + this.age);
    }
}

var pserson = new Person('dadaqianduan');
person.say();

Several call scenarios of this:

var obj = {
    a: 1,
    b: function() {
        console.log(this);
    }
}
  • When called as an object, point to obj.b(); / / point to obj
  • When called as a function, var b = obj.b; b(); / / points to the global window
  • When called as a constructor, var b = new Fun(); // this. Points to the current instance object
  • When calling object.b.apply (object, []); / / this points to the current object as call and apply

Example:

var a = dadaqianduan;
var obj = {
    a: dada
}

function fun() {
    console.log(this.a);
}

fun(); // dadaqianduan
fun.call(obj); // dada
function da(a,b,c) {
    console.log(arguments);
    // Use call/apply to convert arguments into an array and return the result as an array
    var arg = [].slice.call(arguments);
}

da(1,2,3)

this refers to the top-level object in the global context, non strict mode and strict mode.

this === window // true

Function context

var name = 'dadaqianduan';
var fun = function() {
    console.log(this.name);
}
fun(); // 'dadaqianduan'

The call() method calls a function with a specified this value and one or more parameters given separately.

The syntax and function of this method are similar to that of apply(), with only one difference: call() method accepts a parameter list, and apply() method accepts an array with multiple parameters.

Example:

function da(name, age) {
    this.name = name;
    this.age = age;
}

function dada(name, age) {
    da.call(this, name, age);
    this.job = 'it';
}

console.log(new dada('dadaqianduan, 12').name);
// dadaqianduan

Syntax:

function.call(thisArg, arg1, arg2, ...)

Parameter: thisArg, the value of this used when the function is running. This may not be the actual value seen by the method. arg1,arg2,... List of parameters specified.

Return value, the return value of the function is called with this value and parameters provided by the caller. If the method does not return a value, undefined is returned.

Description:

call() allows you to assign and call functions / methods belonging to one object for different objects. Provides a new this value to the currently called function / method. You can use call to implement inheritance.

Using the call method to call the parent constructor

function Person(name, age) {
    this.name = name;
    this.age = age;
} 

function Child1(name, age) {
    Person.call(this, name, age);
    this.eat = 'beff';
}

function Child2(name, age) {
    Person.call(this, name, age);
    this.eat = 'food';
}

var da1 = new Child1('Nezha 1', 12);
var da2 = new Child2('Nezha 2', 12);

Using call method to call anonymous function

var person = [
    {
        name: 'da1',
        age: 1
    },
    {
        name: 'da2',
        age: 2
    }
];

for(var i=0; i<person.length; i++) {
    (function(i){
        this.fun = function() {
            console.log('dadaqianduan');
        }
        this.fun();
    }).call(person[i], i);
}
class Person{
    constructor(name) {
        this.name = name;
    }
    fun(){
        console.log(this.name);
    }
}
let da = new Person('Dada front end');
da.fun(); // Dada front end

For arrow function call, there is no this,super,arguments,new.target Binding cannot be called with new. Without prototype object, the binding of this cannot be changed. Parameter name cannot be duplicate.

The binding object of this is bound to the newly created object, return function or object through new call. The return value is not the newly created object, but the explicit return function or object; the call of call or apply, non strict mode, is null and undefined; the function call on object, bound to this object; the call of ordinary function, strict mode, undefined.

Note: (discuss together)
You can also remember this in objects, methods (functions) in objects, and ordinary functions.

In the binding example, this points to the global object in the non strict mode, and this is bound to the undefined and implicit binding in the strict mode, obj.foo(), this in foo points to obj.

Show binding. call() or apply() methods directly specify the binding object of this. The arrow function indicates that this is determined by the outer scope.

Example:

var a = "dadaqianduan";
function foo () {
  console.log(this.a)
}
foo();

window.a = "dadaqianduan";
function foo() {
  console.log(this.a)
}
window.foo();

// dadaqianduan

Strict mode only makes this in the function point to undefined without changing this point in the global. Only var binds variables to window, while let and const do not.

let a = "dada"
const b = "dada1"

function foo () {
  console.log(this.a)
  console.log(this.b)
}
foo();
console.log(window.a)

// undefined
// undefined
// undefined
var a = "da";
function fun() {
    var a = "da1";
    console.log(this); // window
    console.log(this.a); // so, window.a -> da
}
fun(); // fun called by window
var a = "da";
function fun() {
   // this points to window
    var a = "da1";
    function inner() {
        console.log(this.a);
    }
    inner();
}
fun(); // da

Who finally calls the function, and the this in the function points to the nearest principle.

Example:

function fun() {
    console.log(this.a)
}
var obj = {
    a: 'da',
    fun
}
var a = 'da1';
obj.fun(); // da

// var obj = {fun} => var obj = {fun: fun}

obj object reference fun() assignment obj.fun On, called obj Object, what you print is obj In a

var obj = {
    a: 'da',
    fun: function() {
    // this points to obj
        console.log(this.a)
    }
}

var a = 'da1'
obj.fun()
function fun() {
    console.log(this.a);
};

var obj = {
    a: 'da',
    fun
};

var a = 'da1';

var fun1 = obj.fun;

obj.fun(); // this points to obj - > Da

fun1(); // point obj.fun();, but the window object is called. so, this points to window
// window.fun1()
function fun() {
  console.log(this.a);  
};

var obj = {
    a: 'da',
    fun
};

var a = 'da1';

var fun1 = obj.fun;

var ojb1 = {
    a: 'da2',
    fun2: obj.fun
};

obj.fun(); // this points to obj - > Da

fun1(); // obj.fun () - > the caller is window, so, this points to window, - > DA1
obj1.fun2(); // The caller is obg1, so, this points to obg1
function fun() {
    console.log(this.a);
};

function doFun(fn) {
    console.log(this);
    fn();
};

var obj = {
    a: 'da',
    fun
};

var a = 'da1';

doFun(obj.fun); // obj.fun(); so, this in it points to window - > DA1
function fun() {
    console.log(this.a);
};

function doFun(fn) {
    console.log(this);
    fn();
};

var obj = {
    a: 'da',
    fun
}

var a = 'da1';

var obj1 = {
    a: 'da2',
    doFun
};

obj1.doFun(obj.fun) // Obj 1 object calls doFun(), passing parameters obj.fun , this points to obj 1
// obj.fun() print da1 

//Reason: if a function is passed as an argument to another function, implicit loss will occur, that is, the callback function loses this binding.

// In strict mode, it will be bound to undefined

call,apply,bind

Functions using call and apply will be executed directly. bind is to create a new function, which needs to be called manually.

Example:

function fun() {
    console.log(this.a);
};

var obj = {
    a: 'da'
};

var a = 'da1';

fun(); // da1
fun.call(obj); // da
fun.apply(obj); // da
fun.bind(obj); // Using bind to create a new function will not execute

Example:

If call,apply,bind Receive parameter is empty or null,undefined,This parameter will be ignored

function fun() {
    console.log(this.a);
};

var a = 'da';

fun.call(); // da
fun.call(null); // da
fun.call(undefined); // da
var ojb1 = {
    a: 'da'
};

var obj2 = {
    a: 'da1',
    fun1: function() {
        console.log(this.a); // da1
    },
    fun2: function() {
        setTimeout(function(){
           console.log(this); // window
           console.log(this.a); // window.a -> da2
        },0)
    }
}

var a = 'da2';

obj2.fun1(); // da1
obj2.fun2(); // 
var obj1 = {
    a: 'da'
};

var obj2 = {
    a: 'da1',
    fun1: function() {
        console.log(this.a); // da1
    },
    fun2: function() {
        setTimeout(function() {
            console.log(this); // so,{a:'da'}
            console.log(this.a); // so,da
        }.call(obj1), 0) // Bind external object obg1
    }
}
var a = 'da2';

obj2.fun1();
obj2.fun2();

// Using obp2.fun2.call (obg1) changes the direction of this in fun2 function
var obj1 = {
    a: 'da'
};

var obj2 = {
    a: 'da1',
    fun1: function() {
        console.log(this.a); // da1
    },
    fun2: function() {
        function inner() {
            console.log(this); // window{...}
            console.log(this.a); // da2
        }
        inner();
    }
}
var a = 'da2';
obj2.fun1();
obj2.fun2();
function fun() {
    console.log(this.a);
};

var obj = {
    a: 'da'
};

var a = 'da1';

fun(); // da1
fun.call(obj); // da
fun().call(obj);  // When executing the function of fun() - > DA1 and the return value of the function of fun(), an error will be reported when executing. call(obj)
// Return value of fun() function undefined - > return value of function. call()
function fun() {
    console.log(this.a);
    return function() {
        console.log(this.a);
    }
};

var obj = {
    a: 'da'
};

var a = 'da1';

fun(); // DA1 - > returns an anonymous function. You can use fun()(); to call an anonymous function
fun.call(obj); // Da - > return anonymous function, no call
fun().call(obj); // fun(), the result value da1, returns an anonymous function and binds obj, then this is bound to obj, this.a is obj. A - > the result value is da

// fun().call(obj); -> da1,da

bind binding, just return a new function

Example:

function fun() {
    console.log(this.a);
    return function() {
        console.log(this.a);
    }
}

var obj = {
    a: 'da'
};

var a = 'da1';

fun(); // da1
fun.bind(obj); // No execution, return a new function
fun().bind(obj); // DA1 - > anonymous function binding obj, not called.
function fun() {
    console.log(this.a);
    return function()  {
        console.log(this.a);
    }
}
var obj = {
    a: 'da'
};
var a = 'da1';
fun.call(obj)(); // da , da1

// fun binds obj,this points to obj, anonymous function call
var obj = {
    a: 'da',
    fun: function() {
        console.log(this.a);
        return function() {
            console.log(this.a)
        }
    }
};

var a = 'da1';

var obj1 = {
    a: 'da2'
};

obj.fun()(); // this.a in function, this.a in anonymous function - > window
obj.fun.call(obj1)(); // Bind obj 1, anonymous function returns - > window
obj.fun().call(obj1); // da1, bind obj 1, so, this to obj 2

var da1 = {
    name: 'Nezha the devil',
    sayHello: function(age) {
        console.log(this.name + age);
    }
};

var da2 = {
    name: 'Dada front end',
};

da1.sayHello(12);

// apply,call
da1.sayHello.apply(da2, [12]); // Dada front end 12
da1.sayHello.call(da2, 12); // Dada front end 12
simulation

Function.prototype.applyFun = function(context) {
    context.fn = this;
    context.fn();
    // Remove function reference from context
    delete context.fn;
}

// parameter
Function.prototype.applyFun = function(context) {
    context.fn = this;
    var args = arguments[1];
    context.fn(args.join(',')); // join -> string
    // Execute this function to expand arg with the... Operator of ES6
    // context.fn(...args);
    delete context.fn;
}
var a = 'da';

function sayHello() {
    console.log(this.name);
}

sayHello.apply(null); // If null or no parameter is passed, it is regarded as pointing to window

var a = 'da';

function sayHello() {
    console.log(this.name);
}

sayHello.apply(); // If null or no parameter is passed, it is regarded as pointing to window

Override properties, ES5:

var a = {
    name: 'da'
};

a.name = 'da1'

es6 introduces a primitive data type Symbol, which represents a unique value. The Symbol function can receive a string as a parameter. The Symbol function cannot use the new command. Generating a Symbol is a value of the original type, not an object.

Example:

var s1 = Symbol();
var s2 = Symbol();

s1 === s2 // false

var s1 = Symbol("foo");
var s2 = Symbol("foo");

s1 === s2 // false

When Symbol value is used as object property name, dot operator is not used.

Example:

var mySymbol = Symbol();

// The first way to write
var a = {};
a[mySymbol] = 'Nezha the devil';

// The second way of writing
var a = {
  [mySymbol]: 'Nezha the devil'
};

// The third way of writing
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Nezha the devil' });

// All of the above results are the same
a[mySymbol] // "Nezha the devil"
var a = {};
var name = Symbol();
a.name = 'da1';
a[name] = 'da2';
console.log(a.name,a[name]);             //da1,da2
var obj = {
    a: 'da',
    fun: function(b) {
        b = b || this.a
        return function (c) {
            console.log(this.a + b + c)
        }
    }
}

var a = 'da1';

var obj1 = {
    a: 'da2'
}

obj.fun(a).call(obj1, 1)
// obj.fun (DA1) - > DA1 is passed to parameter b, call changes this, the direction of binding object ojb1, so, this changes, this.a points to object obj 1, which is da2.
// Final results, da2 da1 1

obj.fun.call(obj1)(1)
// Obj1, the binding object of this in the fun function of obj, points to obj 1
// obj.fun.call (obj 1) no parameter passed, so, because B = B | this. A
// so, b is (remember to bind obj 1) DA2. Finally, the anonymous function is called, and the this in the anonymous function points to window.
// da1(this.a refers to window),da2,1


function fun1 () {
    console.log(this.a);
};

var a = 'da';

var obj = {
    a: 'da1'
}

var fun2 = function() {
    fun1.call(obj);
};

fun2(); // da1
fun2.call(window); // da1
function fun1(b) {
    console.log(`${this.a} + ${b}`)
    return this.a + b
}
var a = 1
var obj = {
  a: 3
}

var fun2 = function () {
  return fun1.call(obj, ...arguments)
}

var dada = fun2(5)
console.log(dada)

'3 + 5'
8

// Fun2 (5) - > fun1 binding object obj, so, this.a is obj, a is 3, 5 can be brought in
function fun(item) {
    console.log(item, this.a);
};
var obj = {
    a: 'Nezha the devil'
};
var a = 'dada'

var arr = [1,2,3];
// The second parameter of foreach, map and filter can be bound to this's

arr.filter(function(i){
    console.log(i, this.a);
    return i>2
},obj)

1 'Nezha the devil'
2 'Nezha the devil'
3 'Nezha the devil'
function da (name) {
    this.name = name
};

var name = 'da1';

var dada = new da('da2');
console.log(dada.name) // da2

// New calls the da function, constructs a new object dada, which is bound to this in the da call
var name = 'Nezha the devil';
function fun (name) { // Constructor
    this.name = name;
    this.daFun = function () {
        console.log(this.name);
        return function () {
            console.log(this.name);
        }
    }
}

var da1 = new fun('Nezha 1');
var da2 = new fun('Nezha 2');

da1.daFun.call(da2)()
da1.daFun().call(da2)

Change your mind:

var name = 'Nezha the devil';

// var da1 = new fun('nezha 1 ');
var da1 = {
    name: 'Nezha 1',
    daFun: function() {
        console.log(this.name);
        return function () {
            console.log(this.name);
        }
    }
}

// var da2 = new fun('nezha 2 ');

var da2 = {
    name: 'Nezha 2',
    daFun: function() {
        console.log(this.name);
        return function () {
            console.log(this.name);
        }
    }
}

da1.daFun.call(da2)() // The daFun function binds the da2, points to da2, so, this points to da2, outputs devil Na Zha 2, finally calls (), the internal return function is called by window, and prints the devil Na Zha.
// Nezha the Devil 2, Nezha the devil

da1.daFun().call(da2)

// da1.daFun().call(da2) binds this of anonymous function to da2

// DA1. Dafun() - > Nezha 1 - > Nezha 2

Arrow function

This in the arrow function, determined by the outer scope, points to this when the function is defined, not when it is executed. (discussion)

var obj = {
    name: 'Nezha the devil',
    fun1: () => {
        // The direction of this is determined by the outer scope. It refers to this when the function is defined. It is window
        console.log(this.name)
    },
    fun2: function() {
        console.log(this.name)
        return () => {
            console.log(this.name);
        }
    }
}

var name = 'Dada front end';

obj.fun1(); // this.name  ->Dada front end, when calling, outer layer, when outer scope, window

obj.fun2()(); // this.name  , this.name (anonymous function)

// First look obj.fun2(), and then learn obj.fun2()()
// The first object obj, so that points to calling it is Nezha the devil. The anonymous function inside is the arrow function. When the arrow function points to the definition, it is determined by the outer scope of this. It can be seen that fun2 is the function, so. Then this in the anonymous function will be the same as this in fun2. It's also Nezha the devil.

var name = 'Dada front end';

var obj1 = {
    name: 'Nezha 1',
    fun: function() {
        console.log(this.name)
    }
}

var obj2 = {
    name: 'Nezha 2',
    fun: () => {
        console.log(this.name)
    }
}

obj1.fun() // By obj 1, so, Nezha 1
obj2.fun() // this definition points to the front end of window, so and dada
var name = 'Dada front end';
var obj1 = {
    name: 'Nezha 1',
    fun: function () {
        console.log(this.name);
        return function() {
            console.log(this.name);
        }
    }
}

obj1.fun()(); 
// Obj 1. Fun() - > Nezha the devil, call anonymous function (), the second this.name Call outer layer, so, for dada front end

// Nezha the devil, front end of dada

var obj2 = {
    name: 'Nezha 2',
    fun: function() {
        console.log(this.name);
        return () => {
            console.log(this.name);
        }
    }
}

obj2.fun()(); // obj2.fun() the first value is nezha2, the second arrow function. When this is defined, it points to the outer layer, that is, this, so in obj2, is nezha2

// Nezha 2, Nezha 2

var obj3 = {
    name: 'Nezha 3',
    fun: () => {
        console.log(this.name);
        return function() {
            console.log(this.name)
        }
    }
}

obj3.fun()(); // Dada front end

// first this.name  , the arrow function is determined by the outer scope. When it is defined, it points to window. The memory function is determined by the caller. so is also the front end of dada.

var obj4 = {
    name: 'Nezha 4',
    fun: () => {
        console.log(this.name);
        return () => {
            console.log(this.name);
        }
    }
}

obj4.fun()(); // Dada front end, dada front end, when defined, not when called
var name = 'Dada front end';

function dada (name) {
    this.name = name;
    this.fun1 = function() {
        console.log(this.name);
    }
    this.fun2 = () => {
        // Pointing to the outer scope function dada
        console.log(this.name);
    }
}

var da2 = {
    name: 'da2',
    fun2: () => {
        console.log(this.name);
    }
}

var da1 = new dada('Nezha the devil');
da1.fun1(); // The devil Na Zha, the ordinary function, the caller is dada, (determined by the last caller's object).
da1.fun2(); // Nezha, arrow function, determined by outer scope, when function is defined
// The outer scope is function dada, constructor and new to generate object da1, which points to dada

da2.fun2(); // The scope of da2 is under window. so, build vomit function. this points to window
var name = 'Dada front end',
function dada(name) {
    this.name = name;
    this.fun1 = function() { // Ordinary function
        console.log(this.name);  // Dada
        return function() { // Anonymous function
            console.log(this.name); // Dada front end
        }
    }
    this.fun2 = function() { // Ordinary function
        console.log(this.name); // Dada
        return () => { // Arrow function
            console.log(this.name); // Determined by the outer layer, the outer layer is the dada function, whose value is dada
        }
    }
    this.fun3 = () => { // Arrow function
        console.log(this.name); // Outer layer decision, dada, so, dada
        return function() { // Ordinary function
            console.log(this.name) // Determined by the caller, da1.foo3() returns a normal function. The outer literal of the caller is da1. In window, so, dada front end
        }
    }
    this.fun4 = () => { // Arrow function
        console.log(this.name); // When defined, this points to the outer layer, dada
        return () => { // Arrow function
            console.log(this.name); // Point to the outer layer, dada
        }
    }
}

var da1 = new dada('Dada');

da1.fun1()(); // Dadadada front end
da1.fun2()(); // Dadadada
da1.fun3()(); // Dadadada front end
da1.fun4()(); // Dadadada

This in the arrow function cannot be modified directly by the bind, call, and apply functions. It can be modified by changing the direction of this in the scope.

Example:

var name = 'Dada front end';

var obj1 = {
    name: 'Dada 1',
    fun1: function() { // Ordinary function
        console.log(this.name);
        return () => { // Arrow function
            console.log(this.name);
        }
    },
    fun2: () => { 
        // Arrow function
        console.log(this.name);
        return function() {
            // Ordinary function
            console.log(this.name);
        }
    }
}

var obj2 = {
    name: 'Dada 2'
};

obj1.fun1.call(obj2)() // . call binds object obp2, the first () runs, dada2, and the second (), arrow function. this is the same in the outer fun1 ordinary function, so, dada2

// Dada 2 dada 2

obj1.fun1().call(obj2) // The first call to obj 1, dada 1, returns the arrow function. Call to bind obj 2, wants to change the direction of this to obj 2, but it is invalid, because it is determined by the definition. The execution of this or obj 1, so, output dada 1

// Dada 1 dada 1

obj1.fun2.call(obj2)() // The literal quantity of obj 1,. Call binding obj 2 is invalid. The first one is arrow function, outer scope window, dada front end, dada front end, obj 1.fun2.call (obj 2) points to outer window

// Dada front end

obj1.fun2().call(obj2) // First layer, arrow function, second layer, ordinary function, the first layer is directly the outer scope window, dada front end

// The second layer is bound with obj 2, so and dada 2

// Dada front end, dada 2

Note: the scope of the literal object is window. If it is an arrow function, this points to window

Example:

var name = 'Dada front end';

var da1 = {
    name: 'dada1',
    fun1: function() { // Ordinary function
        console.log(this.name);
    },
    fun2: () => console.log(this.name); // Arrow function
    fun3: function() { // Ordinary function
        return function() { // Anonymous function
            console.log(this.name);
        }
    },
    fun4: function() { // Ordinary function
        return () => { // Arrow function
            console.log(this.name);
        }
    }
}

var da2 = {
    name: 'dada2'
};

da1.fun1(); // Literal da1, ordinary function, caller da1, so, pointing to da1, dada1
// dada1

da1.fun1.call(da2); // this.name Bind da2,so,dada2 through. call
// dada2

da1.fun2(); // Arrow function, pointing to window, so, dada front end
// Dada front end
da1.fun2.call(da2); // . call wants to change the direction, but it doesn't work, dada front end
// Dada front end

da1.fun3()(); // Anonymous function, pointing to window, dada front end
da1.fun3.call(da2); // Return anonymous function, point to window, dada front end
da1.fun3().call(da2); // 

da1.fun3() // Bind da2 through. call, return this normal function, bind da2, so,dada2
//
() {
      console.log(this.name)
    }
//

// dada2

//
function() { // Ordinary function
    return function() { // Anonymous function
        console.log(this.name);
    }
},
//

da1.fun4()(); // When this points to definition, da1, so, dada1
// dada1

da1.fun4.call(da2)(); // If a fun4 is bound to da2 and then runs (), then the return arrow function} in function() {is bound; the outer function is bound to point to da2 and dada2
// dada2

da1.fun4().call(da2); // When defined, fun4() runs, this.name Return to dada1 in
// dada1
var name = 'Dada front end';
function dada(name) {
    this.name = name;
    this.fun1 = function() {
        console.log(this.name);
    },
    this.fun2 = () => console.log(this.name),
    this.fun3 = function() {
        return function() {
            console.log(this.name)
        }
    },
    this.fun4 = function() {
        return () => {
            console.log(this.name)
        }
    }
}

var da1 = new dada('1');
var da2 = new dada('2');

da1.fun1(); // new binds dada, 1
da1.fun1.call(da2); // Binding da2, 2

da1.fun2(); // Arrow function, outer layer or dada, new dada binding dada, 1
da1.fun2.call(da2); // . call wants to change this direction, but it is not valid for arrow function, 1

da1.fun3()(); // Return a normal function, this points to window, dada front end
da1.fun3.call(da2)(); // Bind da2, but it also points to window and dada front end
da1.fun3().call(da2); // Bind da2, return to run (), bind da2, this to da2, 2
// da1.fun3()
Ζ’ () {
      console.log(this.name)
    }
//

da1.fun4()(); // Return arrow function, call da1, point to outer da1, 1
// da1.fun4();
// ->Back
() => {
    console.log(this.name)
}

da1.fun4.call(da2)(); // . call() binds da2, calls (), and the outer layer changes to da2, 2
da1.fun4().call(da2);
// da1.fun4();
// ->Back
() => {
    console.log(this.name)
}
// When defined, points to da1, new dada('1 ') new object, so, is 1
var name = 'Dada front end'
function Person (name) {
  this.name = name
  this.obj = {
    name: 'obj',
    fun1: function () {
      return function () {
        console.log(this.name)
      }
    },
    fun2: function () {
      return () => {
        console.log(this.name)
      }
    }
  }
}
var da1 = new Person('1')
var da2 = new Person('2')

da1.obj.fun1()(); // this refers to the outer window, and the anonymous function refers to the window

da1.obj.fun1.call(da2)(); // The front-end of dada calls ordinary functions, the binding changes the first level function this, and the anonymous function in da2 points to the outer window

da1.obj.fun1().call(da2); // 2. Run the fun1() normal function, return the anonymous function, bind da2, and change this, so in the anonymous function to 2

da1.obj.fun2()(); // Obj, the return arrow function in the ordinary function, obj, so when this points to when the arrow function is defined, return the this.name Obj

da1.obj.fun2.call(da2)(); // 2 fun2, for function() {...}, binding, changing this of the first layer, pointing to da2, so, 2

da1.obj.fun2().call(da2); // Invalid obj arrow function, so, obj
function fun() {
    console.log(this.a); // this.a outer window, da
};
var a = 'da';
(function(){
    // This here points to window. In the following use strict strict mode, this is undefined
    'use strict';
    fun(); // Normal function call / / da
    // this.fun(); in this case, an error will be reported
})();

Direction of this

Example:

function dada() {
    this.a = 'da'; // this points to window, under which window. A ='Da '
    console.log(this.a); // window.a
}
dada(); // da 

this in function dada, determined when the function is called, points to the current running environment of the function

Example:

var a = 'da';
function da() {
    console.log(this.a);
};

var obj = {
    a: 'da1',
    fun: da
};

obj.fun(); // da1

Object method call, pointing to obj

call simulation implementation

Example:

var obj = {
    name: 'dada'
};

function fun() {
    console.log(this.name); // window.name
};

fun.call(obj); // Bind this object obj, dada
// Imagine a change

var obj = {
    // object
    name: 'dada', // attribute
    fun: function() {
        // Ordinary function
        console.log(this.name); // obj.fun() - object obj calls fun() dada
    }
}
obj.fun = Function (assign a function)// Set function as object property
obj.fun()

delete obj.fun This property

var obj = {
    name: 'dada'
};

function fun() {
    console.log(this.name); // window.name
};

fun.call(obj); // Bind this object obj, dada

Look at the above and write the following:

Function.prototype.myCall = function(An object context) {
    context.fun = this; // This in this step refers to the dada() function
    context.fun();
    delete context.fun;
}

var obj = {
    name: 'dada'
};

function dada() {
    console.log(this.name); 
};

dada.myCall(obj); // Object obj, bind this object, this, context.fun = this

// Analog parameter transfer problem call
var obj = {
    value: 'dada'
};

function fun(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}

fun.call(obj, 'da', 12);
// da
// 12
// dada

arguments are class array objects

have a look arguments

arguments = {
    0: obj,
    1: 'da',
    2: 12,
    length: 3
}

The next step is to take out the parameters:

Call the original method, the call is separate

JavaScript eval() function

Definition and Usage

The eval() function evaluates the JavaScript string and executes it as script code.

If the argument is an expression, the eval() function executes the expression. If the argument is a Javascript statement, Eval () executes the Javascript statement.

eval(string)

Function.prototype.myCall = function(context) {
    context.fun = this;
    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }
    eval('context.fun(' + args +')');
    delete context.fun;
}

Note: the parameter can be null

var name = 'dada';
function fun() {
    console.log(this.name);
}
fun.call(null); // this points to window, dada

so change it

Function.prototype.myCall = function (context) {
    var context = context || window;
    context.fun = this;
    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }
    var result = eval('context.fun(' + args +')');
    delete context.fun
    return result;
}

apply simulation implementation

Example:

Pass in an object, and an array
//Code from @ Nuggets

Function.prototype.apply = function (context, arr) {
    var context = Object(context) || window;
    context.fn = this;

    var result;
    if (!arr) {
        result = context.fn();
    }
    else {
        var args = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            args.push('arr[' + i + ']');
        }
        result = eval('context.fn(' + args + ')')
    }

    delete context.fn
    return result;
}

bind Simulation Implementation

bind binding function, feature, return a function, parameter can be passed

Example:

var obj = {
    name: 'da';
};

function fun() {
    console.log(this.name);
}

// Returns a function
var da1 = fun.bind(obj);

da1(); // da

Bind() method creates a new function. When bind() is called, this of the new function is pointed to the first parameter of bind(), binding object, and other parameters will be parameters of the new function.

Bind changes the direction of this function, but instead of executing the function immediately, bind returns a new function bound to this.

Simulation Implementation:

The first step of simulation implementation:

Function.prototype.myBind = function(context){
    var that = this
    return function(){
        return that.apply(context)
    }
}

// Writing method 2

Function.prototype.bind_ = function (obj) {
    var fn = this;
    return function () {
        fn.apply(obj);
    };
};

The second step of simulation implementation: support function parameter transfer

Function.prototype.myBind = function (context) {
    var that = this; // function
    var args = Array.prototype.slice.call(arguments, 1);
    return function () {
        var bindArgs = Array.prototype.slice.call(arguments);
        return that.apply(context,args.concat(bindArgs));
    }

}

// Writing method 2

Function.prototype.bind_ = function (obj) {
    // 0 is this, so start from the first
    var args = Array.prototype.slice.call(arguments, 1);
    var fn = this;
    return function () {
        fn.apply(obj, args);
    };
};

Function.prototype.bind_ = function (obj) {
    var args = Array.prototype.slice.call(arguments, 1);
    var fn = this;
    return function () {
        // Secondary call
        var params = Array.prototype.slice.call(arguments); 
        
        fn.apply(obj, args.concat(params));
    };
};

Add this judgment and prototype inheritance

Function.prototype.bind_ = function (obj) {
    var args = Array.prototype.slice.call(arguments, 1);
    var fn = this;
    var instanceObj = function () {
        var params = Array.prototype.slice.call(arguments);
        // Judging the calling mode by constructor
        // true this points to an instance, otherwise obj
        fn.apply(this.constructor === fn ? this : obj, args.concat(params));
    };
    //Prototype chain inheritance
    instanceObj.prototype = fn.prototype;
    return instanceObj;
};

Simulation implementation revision:

Function.prototype.bind = Function.prototype.bind || function (context) {
    var me = this;
    var args = Array.prototype.slice.call(arguments, 1);
    var F = function () {};
    F.prototype = this.prototype;
    var bound = function () {
        var innerArgs = Array.prototype.slice.call(arguments);
        var finalArgs = args.concat(innerArgs);
        return me.apply(this instanceof F ? this : context || this, finalArgs);
    }
    bound.prototype = new F();
    return bound;
}

// modify
Function.prototype.myBind = function(obj) {
  // It must be a function to call the bind method
  if(typeof this !== "function")  {
      throw new Error('error')
  };
  var args = Array.prototype.slice.call(arguments, 1);
  var fn = this;
  
  var fn_ = function () {};
  var instanceObj = function () {
       var params = Array.prototype.slice.call(arguments);
       fn.apply(this.constructor === fn ? this : obj, args.concat(params));
       console.log(this);
  };
   fn_.prototype = fn.prototype;
   instanceObj.prototype = new fn_();
   return instanceObj;
};

See this realization: (discuss together, you can write an article to show me)

bind: function bind(that) {
    var target = this;
    if (!isCallable(target)) {
        throw new TypeError('Function.prototype.bind called on incompatible ' + target);
    }
    var args = array_slice.call(arguments, 1);
    var bound;
    var binder = function () {
        if (this instanceof bound) {
            var result = target.apply(
                this,
                array_concat.call(args, array_slice.call(arguments))
            );
            if ($Object(result) === result) {
                return result;
            }
            return this;
        } else {
            return target.apply(
                that,
                array_concat.call(args, array_slice.call(arguments))
            );
        }
    };
    var boundLength = max(0, target.length - args.length);
    var boundArgs = [];
    for (var i = 0; i < boundLength; i++) {
        array_push.call(boundArgs, '$' + i);
    }
    bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);

    if (target.prototype) {
        Empty.prototype = target.prototype;
        bound.prototype = new Empty();
        Empty.prototype = null;
    }
    return bound;
}

extend

Documents on MDN:

The bind() method creates a new function, when called, sets its this keyword to the provided value, when calling the new function, provides the given parameter sequence before any provision

The apply() method calls a function with a specified this reference and the parameters provided as an array

es6 mode, example:

Function.protype.myCall = function(context) {
    var context = context || window;
    context.fun = this;
    var args = [];
    for(var i=1, len = arguments.length; i<len; i++) {
        args.push(arguments[i]);
    }
    context.fun(...args)
    delete context.fun
}
Function.prototype.myCall = function(context,...args) {
    context = context || window;
    context.fun = this;
    let temp = context.fun(...args);
    delete context.fun;
    return temp;
}

Note: never use eval!

new() in js

Please tell me what you did with the new operator in js

1. Create an empty object

2. Link to prototype

3. Bind this point, execute constructor

4. Make sure the object is returned

Example:

var obj = new da();

var obj = {};
obj.__proto__ = da.prototype;
da.call(obj);
function A(){}
var a = new A();
a.__proto__ === A.prototype //true

// Prototype chain
    
A.__proto__ === Function.prototype //true

Add: prototype and__ proto__

Each function has a prototype property, and each object instantiated by the function contains an implicit pointer (__ proto__) The prototype property pointing to the function

new operator

  • Create an empty JavaScript object {}
  • Link this object to another
  • Make the newly created object the context of this
  • If the function does not return an object, this is returned

Example:

function da(name, age, year) {
  this.name = name;
  this.age = age;
  this.year = year;
}

const da1 = new da('dada', '12', 2333);

console.log(da1.name);
// expected output: "dada"
function create(){
    // Create an empty object  
    let obj = new Object();
    // Get constructor
    let Constructor = [].shift.call(arguments);
    // Link to prototype
    obj.__proto__ = Constructor.prototype;
    // Bind this
    let result = Constructor.apply(obj,arguments);
    // Return to new object
    return typeof result === "object" ? result : obj; 
    // let obj = new Object();
}

Object.create Simulation Implementation of:

Object.create = function( o ) {
    function f(){}
    f.prototype = o;
    return new f;
};

reference

If you look at it quietly, you will surely get something!

Using call and apply to simulate the bind method of ES5

[suggestions πŸ‘ ]Another 40 interview questions of this continue (1.2w words by hand)

JavaScript in-depth call and apply simulation implementation

The simulation implementation of bind in JavaScript

Interviewer: can you simulate the bind method of JS

about

Author: he often wanders in the front-end Jianghu.
Personal blog
github blog , find a star^_ ^

WeChat official account dada front end

Perhaps the more interesting WeChat official account is long. You can also add the wechat xiaoda0423, indicate the source, and pull you into the [dada front-end communication group]. -Indicate source

Posted by robotta1530 on Wed, 10 Jun 2020 23:31:30 -0700