简体   繁体   中英

Why does this function with “this” not work? About “this” and its scope

I know that adding a method to the prototype this way is not the best, but I'm just testing.

 Array.prototype.maap = function (transform) { let mapped = []; for (let element of this) { mapped.push(transform(element)); } return mapped; } console.log([0, 2, 3].maap(n => n / this.length)); 

I am getting:

[NaN, Infinity, Infinity]. I think the problem is "this.length".

You're right, the problem is this.length . The trouble is that it's not in the function ! It's in a lambda, whose scope is not that of the array by which it's later invoked. As such, this is not the array, and this.length is a solid 0 (0/0 being NaN, 2/0 being infinity and 3/0 also being infinity).

You can either hardcode the real value 3 , or move your logic into the function itself. Or you could have the lambda (actually an "arrow function" in JavaScript) take another parameter: that of the denominator.

 Array.prototype.maap = function (transform) { let mapped = []; for (let element of this) { mapped.push(transform(element, this.length)); } return mapped; } console.log([0, 2, 3].maap((n, m) => n / m)); 

this inside an arrow function references the same this in its containing block. Here, the containing block is the top level, where this refers to window , and window.length is 0 .

 console.log(this === window); console.log(window.length); 

So, your code is equivalent to:

 Array.prototype.maap = function(transform) { let mapped = []; for (let element of this) { mapped.push(transform(element)); } return mapped; } console.log(this.length); console.log([0, 2, 3].maap(n => n / 0)); 

0 / 0 is undefined , while most any other number / 0 is Infinity (or -Infinity ).

If you want to emulate Array.prototype.map 's behavior with this , the second argument passed to maap should be the this value the callback is invoked with:

 Array.prototype.maap = function(transform, thisVal) { let mapped = []; for (let element of this) { mapped.push(transform.call(thisVal, element)); } return mapped; } const arr = [0, 2, 3]; console.log(arr.maap( function(n){ return n / this.length; }, arr )); 

I think the problem is on the arrow function (the param transform ), Yes, this.length is the directly related questions, go deeper, it's a problem about arrow function ,

An arrow function does not have its own this . The this value of the enclosing lexical scope is used;

Simply put, where the arrow function defined where the this point.

So, for your code, The parameters you passed in is n => n / this.length , and it is defined in function console.log in the environment of window . So the real problem is:

transf = (n) => {
  console.log(this);    // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
  return n / this.length
}
console.log([0, 2, 3].maap(transf));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM