简体   繁体   中英

Bind scoping javascript

I'm trying to figure out scoping of using bind. I'm confused about the output of boundF1 . What is going on here?

// console.log(x) ReferenceError: x is not defined

// setting this.x - this here is global or window
this.x = 5;
console.log(x) // 5

function f1() {
  console.log(x); // 5
  console.log(this.x); // 5
}

// Lexically bound this to window 
f2 = () => {
  console.log(x); // 5
  console.log(this.x); // 5
}

f1()
f2()

boundF1 = f1.bind({x:1});
boundF2 = f2.bind({x:1});


boundF1() // 5 1 Why is this not 1, 1. How is x resolved here? Does it check local vars, then global vars. Would it ever use this? What is the scoping rule?

boundF2() // 5 5

Cause x will always look up the variable in the scope . It has nothing todo with this (the context ). When you call .bind , you only set the value of this inside of a function.

in f2, because it's an unbindable arrow function, x and this.x both refer to window.x .

In f1, x will first try to find any locally scoped variable x and if it can't, will search for an x in the global scope. But because it's bound, this no longer refers to window but to the object you bound it to, so this.x is the x-value of the object you bound it to.

When you reference a standalone variable, like console.log(x) , the interpreter will try to find a standalone variable with that same name somewhere in the outer scope. Here, the outer scope eventually gets to the global scope, and so console.log(x) resolves to console.log(window.x) .

Properties of this do not get added to a function's variable environment; to reference properties of this , you have to do so explicitly, eg:

console.log(this.x);

Not that you should ever use it, but there is with , which lets you reference properties of an object as if they were standalone variables (which sounds like what you were thinking would happen automatically), but it's highly not recommended (and forbidden in strict mode).

 this.x = 5; function f1() { with (this) { console.log(x); // 5 console.log(this.x); // 5 } } boundF1 = f1.bind({x:1}); boundF1() 

In the function f1() in the first print statement you are printing x not this.x , so when you bind it with the object {x:1} with the Function.prototype.bind() you are passing the this as {x:1} object. But in the function you are reading the value of x from the global scope not from the this context you have bound to.

So when you execute the function f1 and printing x it is looking for the x in local scope first, since it didn't find any it will look up in the parent scope which is the global scope in this case.

If there were no x declared in the global scope you would have gotten a ReferenceError :

 function f1() { console.log(this.x); // 1 console.log(x); // ReferenceError as x is not declared in any scope } f1.bind({x:1})(); 

The scope rules are explained in the MDN docs :

Scopes can also be layered in a hierarchy, so that child scopes have access to parent scopes, but not vice versa.

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