我在确定什么概念解释为什么将对象的属性“ count”的值保留在下面的代码中时感到困难。
我已阅读并阅读了Getify的You Don't Know JS的此和对象原型部分 以及他们解释lexical this的部分。 但是,我无法在下面理解我的代码。 这是词汇作用域吗? 还是这个绑定可以保留count的值?
下面是示例代码:
var obj = {
count: 0,
method: function() {
console.log("in method: " + this.count)
return this.count++;
},
timeOutMethod: function() { // I understand here we explicitly bind this, no problem here
setTimeout(function() {
console.log(this.count++)
}.bind(this), 100)
}
}
// here is where I have issue, when the method is invoked as a function
for (var i = 0; i<10; i++) {
console.log(obj.method()) // invoked as a function
}
// I've left this small block in for convenience
// I have no trouble with understanding why this block outputs what it outputs
for (var i = 0; i<10; i++) {
console.log(obj.method) // "gets its value (a reference to a function) and then logs that" from TJ Crowder
}
我希望对obj.method()的第一个方法调用的输出能够输出
// 0
// in method 0
// 1
// in method 1
// 2
.
.
.
// 10
// in method 10
我对输出内容没有问题。我的问题再次是,这是词汇作用域吗? 还是这个绑定可以保留count的值?
感谢您抽出宝贵的时间来提供帮助。
编辑1 在下面Tj Crowder的帖子的帮助下,我编辑了代码段以清除错误,因为它使我的问题分散了注意力。
答案 0 :(得分:3)
此问题与this
或作用域无关。 :-)您看到undefined
是因为method
不返回任何内容,因此调用它会得到值undefined
,您将通过console.log
进行记录。要使其返回 count
的值,您可以添加一个return
:
method: function() {
console.log(this.count)
return this.count++;
// ^^^^^^
},
这将返回this.count
的值,该值与增量之前的值相同(这似乎是您从预期输出中得到的值)。
实时示例:
var obj = {
count: 0,
method: function() {
console.log("in method: " + this.count)
return this.count++;
},
timeOutMethod: function() { // I understand here we explicitly bind this, no problem here
setTimeout(function() {
console.log(this.count++)
}.bind(this), 100)
}
}
// here is where I have issue, when the method is invoked as a function
for (var i = 0; i<10; i++) {
console.log(obj.method()) // invoked as a function
}
.as-console-wrapper {
max-height: 100% !important;
}
另外,对此:
for (var i = 0; i<10; i++) {
console.log(obj.method) // invoked as a property
}
根本不调用 method
的,它只是获取其值(对函数的引用),然后记录该值(您将在控制台)。
答案 1 :(得分:1)
它具有绑定力。
作用域是可访问的变量以及语言对您隐藏的变量的概念。在机器语言中,所有内存地址都是可读写的,因此在机器语言和某些汇编语言中,作用域的概念不存在(所有变量基本上都是全局变量)。后来的语言通过函数的引入引入了全局变量与局部变量的概念。此概念进一步演变为闭包-创建作用域的多个实例的功能。
绑定是哪个属性/属性属于哪个对象的概念。在实现早期绑定的Java和C ++之类的语言中,绑定的概念仅控制方法访问属性的方式(通常,这使该语言不需要“ this”关键字)。后期绑定语言的规则稍微复杂一些,因为绑定是在运行时而不是编译时确定的。 JavaScript不仅是后期绑定,而且是动态绑定-允许程序员更改此指向的对象,以使用诸如Function.prototype.call()
之类的对象。并在运行时将一个对象的方法分配给另一个对象(例如b.foo = a.foo
)
答案 2 :(得分:0)
TL; DR 将属性count
绑定到this
值的机制是隐式绑定 (Getify's You Don't Know JS), Implicit Binding
首先:如果我在解释中得出了错误的结论,您是否愿意提供您同意或不同意的内容,并分享我应如何考虑这个问题?我想要改善,谢谢!
说明:调用obj.method()
时,我们将对this.count
进行属性查找。如果我们在调用obj.method()
时检查呼叫站点,则obj
是全局范围内的变量。
obj
的属性通过原型链访问。当我们执行this.count
的属性查找时,我们尝试访问obj中的属性。当找不到该属性时,我们将查找该属性的原型链。在我们通过“ this”绑定访问obj.count
属性时,count
包含/拥有属性count
。
我的问题的原因:我混合了this
绑定如何在箭头框架中操作,词法范围以及对“ this”的解释过于文字化的概念。 / p>
示例
下面是使我感到困惑的代码示例。
我的问题源于将this
-绑定如何以不同的代码样式进行操作的约定混为一谈。我混合了以下内容:
this
关键字如何在箭头功能(即词法作用域)中运行
function wait() {
setTimeout(() => {
console.log(this) // lexically bound
}, 100);
}
wait();
function foo() {
// console.log(this) - will output {a: 2}
return (a) => {
console.log(this.a) // 'this' value is adopted from foo's lexical scope
}
}
var obj = {
a: 2
}
var obj2 = {
a: 3
}
// foo is 'this'-bound to obj1
// bar, a reference to the returned arrow-function will also be 'this'-bound to obj1
// the arrow function binding cannot be overridden
var bar = foo.call(obj)
bar.call(obj2)
不是理解this
的实际工作原理,而是将词法作用域用作解决方法。在这里,data.count增加了
function foo() {
return data.count++; // the obj property data.count is accessed via global scope
}
var data = {
count: 0,
}
for (var i = 0; i<10; i++) {
foo()
}
console.log(data.count)
最后,对this
-绑定的解释过于文字化,可能会引起另一个误解。我引用的摘录来自Getify的书
function foo(num) {
console.log( "foo: " + num );
// keep track of how many times `foo` is called
this.count++;
}
foo.count = 0;
var i;
for (i=0; i<10; i++) {
if (i > 5) {
foo( i );
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9
// how many times was `foo` called?
console.log( foo.count ); // 0 -- not what we expected
此外:感谢@TJ Crowder和@slebetman在澄清关于范围和this
绑定的其他误解方面所提供的帮助