javascript 函数中的静态变量及其背后的工作原理
static variables within javascript functions and how it works under the hood
我很难理解 JavaScript 中的一些基本概念,所以我希望有人能给我一个很好的解释,说明这些示例中发生的事情。
案例 1:
在这种情况下,我在构造函数中使用 'this' 关键字:
function Counter() {
this.c = 0;
this.incC = function() {
return this.c++;
};
}
显然,现在我可以实例化函数并调用 incC 函数来递增 c,并且 c 的记录将保存在创建的实例中,因为 'this' 指的是正在创建的实际对象。根据我在 C 中的(有限)编程经验,我想当我这样做时:
var counter = new Counter();
-代码有效地为对象分配 space,然后将指向该分配内存的指针传递给构造函数,该指针是 'this'.
但我想知道我是否错了,因为万一 2 事情有点不同。
案例 2:
在这个函数中,我可以使用 'this' 关键字创建一个持久变量。但是,我不打算实例化它,所以它不能指向一个对象,而且它似乎不是 counter 的属性(显然函数本身是一个对象)作为 counter.c returns未定义。
function counter() {
this.c = this.c || 1;
return this.c++;
}
console.log(counter.c); // undefined
那么这个例子中到底发生了什么?为什么以及如何在我们退出函数时不丢失 c,以及在这个例子中 'this' 指向什么?
案例 3:
最后只是为了让事情变得更有趣。
我在一个非常古老的代码库中遇到了这个问题(我知道有更准确的继承方法,但发现这个例子很有趣,因为它是如何工作的):
function CounterChild() {
Counter();
}
CounterChild.prototype = new Counter();
CounterChild.constructor = CounterChild;
var child = new CounterChild();
console.log(child.c); // 0
这里的 this 关键字与正在实例化的对象相关,但是对 Counter() 构造函数的调用究竟是如何传递对正在创建的对象的引用的呢?我的意思是解释器怎么知道应该向这个函数传递一个指针,因为没有使用新的关键字?
关于 this
最重要的一点是,它的值由 如何 函数 调用 决定(预计对于 ES6 箭头函数,其中 this
是词法作用域,以及通过 .bind
).
绑定的函数
调用 new Counter()
与调用 Counter()
非常不同,因此 this
指的是不同的值。
总体而言,我建议阅读 MDN - this
以了解有关 this
的更多信息。
案例一
是
案例二
由于函数调用"normally",即foo()
,this
指的是全局对象,在浏览器中是window
。代码相当于
function counter() {
window.c = window.c || 1;
return window.c++;
}
案例三
how exactly does the call to the Counter() constructor get passed a reference to the object being created?
没有。在 CounterChild()
中调用 Counter
在这里没有可见效果 (*),您可以简单地删除它。
c
属性 来自 CounterChild.prototype.c
,因为您将 Counter
实例分配给 CounterChild.prototype
。您可以通过检查 console.dir(child)
.
来验证这一点
CounterChild.prototype
是通过new CounterChild()
创建的所有实例的原型。在对象的原型链中查找对象本身不存在的任何 属性。
如果想让Counter
里面的this
引用新创建的对象,必须显式传递:
function CounterChild() {
Counter.call(this);
}
*:事实并非如此。就像情况 2 一样,它确实更改了 全局变量 c
,但这绝对不是您想要的。
我很难理解 JavaScript 中的一些基本概念,所以我希望有人能给我一个很好的解释,说明这些示例中发生的事情。
案例 1:
在这种情况下,我在构造函数中使用 'this' 关键字:
function Counter() {
this.c = 0;
this.incC = function() {
return this.c++;
};
}
显然,现在我可以实例化函数并调用 incC 函数来递增 c,并且 c 的记录将保存在创建的实例中,因为 'this' 指的是正在创建的实际对象。根据我在 C 中的(有限)编程经验,我想当我这样做时:
var counter = new Counter();
-代码有效地为对象分配 space,然后将指向该分配内存的指针传递给构造函数,该指针是 'this'.
但我想知道我是否错了,因为万一 2 事情有点不同。
案例 2:
在这个函数中,我可以使用 'this' 关键字创建一个持久变量。但是,我不打算实例化它,所以它不能指向一个对象,而且它似乎不是 counter 的属性(显然函数本身是一个对象)作为 counter.c returns未定义。
function counter() {
this.c = this.c || 1;
return this.c++;
}
console.log(counter.c); // undefined
那么这个例子中到底发生了什么?为什么以及如何在我们退出函数时不丢失 c,以及在这个例子中 'this' 指向什么?
案例 3:
最后只是为了让事情变得更有趣。
我在一个非常古老的代码库中遇到了这个问题(我知道有更准确的继承方法,但发现这个例子很有趣,因为它是如何工作的):
function CounterChild() {
Counter();
}
CounterChild.prototype = new Counter();
CounterChild.constructor = CounterChild;
var child = new CounterChild();
console.log(child.c); // 0
这里的 this 关键字与正在实例化的对象相关,但是对 Counter() 构造函数的调用究竟是如何传递对正在创建的对象的引用的呢?我的意思是解释器怎么知道应该向这个函数传递一个指针,因为没有使用新的关键字?
关于 this
最重要的一点是,它的值由 如何 函数 调用 决定(预计对于 ES6 箭头函数,其中 this
是词法作用域,以及通过 .bind
).
调用 new Counter()
与调用 Counter()
非常不同,因此 this
指的是不同的值。
总体而言,我建议阅读 MDN - this
以了解有关 this
的更多信息。
案例一
是
案例二
由于函数调用"normally",即foo()
,this
指的是全局对象,在浏览器中是window
。代码相当于
function counter() {
window.c = window.c || 1;
return window.c++;
}
案例三
how exactly does the call to the Counter() constructor get passed a reference to the object being created?
没有。在 CounterChild()
中调用 Counter
在这里没有可见效果 (*),您可以简单地删除它。
c
属性 来自 CounterChild.prototype.c
,因为您将 Counter
实例分配给 CounterChild.prototype
。您可以通过检查 console.dir(child)
.
CounterChild.prototype
是通过new CounterChild()
创建的所有实例的原型。在对象的原型链中查找对象本身不存在的任何 属性。
如果想让Counter
里面的this
引用新创建的对象,必须显式传递:
function CounterChild() {
Counter.call(this);
}
*:事实并非如此。就像情况 2 一样,它确实更改了 全局变量 c
,但这绝对不是您想要的。