this points to the issue ES5

pointer to this in ES5

According to thisthe priority of the pointer, list the following four situations that are often encountered, from top to bottom, the priority is from high to low (the priority will be compared in detail later).

  1. Is the function newcalled with ( new binding )? If it is, thisit is the newly constructed object.

    var bar = new foo()

  2. Is the function used callorapply called ( explicitly bound ), or even hidden in bind hard bindings  ? If it is, thisit is an explicitly specified object.

    var bar = foo.call( obj2 )

  3. Is the function called with an environment object (also called an owner or container object) ( implicit binding )? If it is, thisit is that environment object.

    var bar = obj1.foo()

  4. Otherwise, the default this( default binding ) is used. If it is strict modeunder , it is undefined, otherwise it is an globalobject. var bar = foo()

That's all you need to understand the thisbinding rules for ordinary function calls. Yes...almost all.

apply、call、bind

Because apply and call exist in Function.prototype, each method has these two properties.

  • call
函数名.call(对象,arg1....argn)
//功能:
    //1.调用函数
    //2.将函数内部的this指向第一个参数的对象
    //3.将第二个及以后所有的参数,作为实参传递给函数
  • The main purpose of apply
    is to pass parameters directly with an array
函数名.apply(对象, 数组/伪数组);
//功能:
    //1.调用函数
    //2.将函数内部的this指向第一个参数的对象
    //3.将第二个参数中的数组(伪数组)中的元素,拆解开依次的传递给函数作为实参
//案例求数组中最大值 var a=Math.max.apply( null, [ 1, 2, 5, 3, 4 ] ); console.log(a);// 输出:5
  • bind
  1. is to create a new function, we have to call it manually:
var a ={
  name : "Cherry",
  fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.bind(a,1,2)() // 3
  • Precautions

    1. The functions of call and apply are almost the same, the only difference is the way of passing parameters! !
      2. If the first parameter of call and apply is null or undefined, then this points to window
      3. If the first parameter of call and apply is data of value type, then the data of this value type will be converted into its corresponding The data of the reference type, and then point this to the data of this reference type.
      4.call and apply execute the function immediately. The bind method allows the corresponding function to be called whenever it wants, and the parameters can be called at the time of execution. Add, this is the difference between them, choose to use according to your actual situation.
      5. When the number of parameters is determined, you can use call; when the number of parameters is uncertain, you can use apply

applyApply

JavaScript

var array1 = [12 , "foo" , {name "Joe"} , -2458]; var array2 = ["Doe" , 555 , 100]; Array.prototype.push.apply(array1, array2); /* array1 值为 [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

call application (convert pseudo-array to array)

var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 } Array.prototype.join.call(arrayLike, '&'); // name&age&sex Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"] // slice可以做到类数组转数组 Array.prototype.map.call(arrayLike, function(item){ return item.toUpperCase(); }); // ["NAME", "AGE", "SEX"]

call application (judging complex data types)

console.log(
    Object.prototype.toString.call(num),
    Object.prototype.toString.call(str),
    Object.prototype.toString.call(bool),
    Object.prototype.toString.call(arr), Object.prototype.toString.call(json), Object.prototype.toString.call(func), Object.prototype.toString.call(und), Object.prototype.toString.call(nul), Object.prototype.toString.call(date), Object.prototype.toString.call(reg), Object.prototype.toString.call(error) ); // '[object Number]' '[object String]' '[object Boolean]' '[object Array]' '[object Object]' // '[object Function]' '[object Undefined]' '[object Null]' '[object Date]' '[object RegExp]' '[object Error]'

Bind is applied in react

The following example is a case from the react official website

class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // This binding is necessary to make `this` work in the callback this.handleClick = this.handleClick.bind(this); } handleClick() { console.log(this); this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'} </button> ); } } ReactDOM.render( <Toggle />, document.getElementById('root') );

If you forget to bind this.handleClick and pass it to onClickthis will be undefined when the function is actually called.

Point to this in ES6

Arrow function this points to note

The object in the body of the arrow function this, if it is wrapped in the function, is the object where the function is called, and if it is placed in the global, it refers to the global object window. And fixed does not change. In other words , the inner part thisis the outer code block.this

The following is a comparative analysis of the difference between this in ordinary functions and arrow functions

// 普通函数
function foo() { setTimeout(function() { console.log('id:', this.id); }); } var id = 21; foo.call({ id: 42 }); //21
// 箭头函数
function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 }); //42 // 上面的匿名函数定义时所在的执行环境就是foo函数,所以匿名函数内部的this执向始终会和foo函数的this执向保持一致,不会更改,如同下面的这个案例 function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo(); //21(没有用call)
// ES5普通函数模拟上面es6函数的执行过程
function foo() { var _this = this; setTimeout(function () { console.log('id:', _this.id); }, 100); }

The function of call is to change the execution environment of the foo function from window to the object {id: 42}
timer. The function of the timer is to delay the execution of the external execution environment of the current function, regardless of whether the delay time is set or not.

Ordinary function explanation: this points to the function fooscope when it is defined, but when the function is executed 100 milliseconds after the timer, this points to the window object at this time

Arrow function explanation: this always points to the object where it was defined, that is, always points to the fooscope

Further analysis of this

var handler = {
  id: '123456',

  init: function() { document.addEventListener('click', event => this.doSomething(event.type), false); }, doSomething: function(type) { console.log('Handling ' + type + ' for ' + this.id); } }; handler.init()// Handlingclickfor123456

The this of the arrow function always points to handler, if it is a normal function, this points todocument

thisThe fixed point is not because there is a binding thismechanism inside the arrow function. The actual reason is that the arrow function does not have its own at all this, resulting in the inner thiscode blockthis . Precisely because it doesn't this, it can't be used as a constructor.

Considerations (Binding Events)

In IE678, addEventListener and removeEventListener are not supported, but two methods, attachEvent and detachEvent, are supported.

语法:target.attachEvent(“on”+type, listener);

The difference between attachEvent and addEventListener:

  1. This in the attchEvent points to not the caller of the event, but the window (wonderful) , and the caller of the event pointed to by addEventListener.
  2. The type of attachEvent must be added on, otherwise it will have no effect

interview questions

The following interview questions 1, 2, and 4 are all designed to refer to the question. If it is not well understood, it can be understood that in es5, this always points to the object that called it last. excerpt link

The following concepts related to pointer applications and bindings are taken from the You Dont Konw JS link

interview question one

this.x = 9;    // this refers to global "window" object here in the browser
var module = { x: 81, getX: function() { return this.x; } }; module.getX(); // 81 var retrieveX = module.getX; retrieveX(); // returns 9 - The function gets invoked at the global scope // Create a new function with 'this' bound to module // New programmers might confuse the // global var x with module's property x var boundGetX = retrieveX.bind(module); boundGetX(); // 81

retrieveXIt's just getXa reference to the function, which is just getXa pointer ( getXthe other pointer is module.getX), so it retrieveXstill points to the getXfunction itself

Similar to the case above, the following func is just a function reference, so even inside the function, it is still the executed function itself, which is not restricted by lexical scope (arrow functions are restricted)

document.getElementById( 'div1' ).onclick = function(){ console.log( this.id );// 输出: div1 var func = function(){ console.log ( this.id );// 输出: undefined } func(); }; //修正后 document.getElementById( 'div1' ).onclick = function(){ var func = function(){ console.log ( this.id );// 输出: div1 } func.call(this); }; 
function foo() { console.log( this.a ); } var a = 2; var o = { a: 3, foo: foo }; var p = { a: 4 }; o.foo(); // 3 (p.foo = o.foo)(); // 2

Interview question two

var A = function( name ){ 
    this.name = name; }; var B = function(){ A.apply(this,arguments); }; B.prototype.getName = function(){ return this.name; }; var b=new B('sven'); console.log( b.getName() ); // 输出: 'sven'

Interview question three

Indeed, many functions in packages, and many built-in functions in the JavaScript language and the host environment, take an optional parameter, often called a "context", designed as an alternative to ensure that you The callback function uses a specific this instead of having to use bind(..).

for example:

function foo(el) {
    console.log( el, this.id ); } var obj = { id: "awesome" }; // 使用`obj`作为`this`来调用`foo(..)` [1, 2, 3].forEach( foo, obj ); // 1 awesome 2 awesome 3 awesome

Interview question four

Explicit binding  takes precedence over implicit binding

function foo() { console.log( this.a ); } var obj1 = { a: 2, foo: foo }; var obj2 = { a: 3, foo: foo }; obj1.foo(); // 2 obj2.foo(); // 3 obj1.foo.call( obj2 ); // 3 obj2.foo.call( obj1 ); // 2

The priority of new binding is higher than implicit binding (new and call/apply cannot be used at the same time, so new foo.call(obj1) is not allowed, that is, new binding and explicit binding cannot be tested directly)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325098796&siteId=291194637