你的观点是错误的。请看我的另一个回答。
看,如果你使用new
,那么this
在构造函数的范围内将指向返回的对象。
var Point2D = function (x, y) {
this.x = x;
this.y = y;
this.setX = function (x) { this.x = x; };
this.setY = function (y) { this.y = y; };
};
var point1 = new Point2D(1, 5),
point2 = new Point2D(2, 3);
point1.setX(7);
point2.setY(32);
我的嵌套函数被设置为正在创建的全新“this”的属性。
如果我在构造函数中有辅助函数:
Point2D = function (x, y) {
function roundX () { return Math.floor(this.x); }
function roundY () { return Math.floor(this.y); }
}
这些函数不是作为对象的属性添加的,因此this
在它们内部调用window
, 而不是。
这就是 JS 的工作方式。
要么一个函数直接是一个对象的属性,要么你使用.call()
或.apply()
传递一个不同this
的函数,或者函数使用window
.
还:
是的,函数是对象。
但this
在我的Point2D
示例内部并没有指向 Point2D 函数......
它指向一个全新的对象,该对象被制作并返回。
如果您忘记使用new
,猜猜什么会被用作this
,而不是?
window
做。
没有什么真正的神奇之处。
当您使用像我的 Point2D 构造函数这样的函数时,该函数会检查是否new
被调用。如果是这样,那么this = {};
就是在函数开始时在幕后发生的事情。如果不是,那么this = window
就是所谓的。
但是嵌套函数也是如此。被new
使用了吗?然后嵌套函数对一个 100% 全新的对象进行操作。否则,它在window
.
唯一的四种解决方法是:
function sayName () { console.log(this.name); }
var bob = { name : "Bob" };
1).call(new_this)
sayName.call(bob); // Bob
证明函数是对象——它们都有自己的属性/方法
2).apply(new_this)
sayName.apply(bob); // Bob
.apply
并且.call
除了参数如何传递给函数之外是相同的。
如果我.call
在 Point2D 上使用,它看起来像:
var obj = {},
x = 1,
y = 3;
Point2D.call(obj, x, y);
现在,Point2D 不再创建新对象,而是在obj
.
如果我要使用.apply
它看起来像:
var obj = {},
x = 1,
y = 3;
Point2D.apply(obj, [x,y]);
全部区别在于您传递一个数组,而不是一次传递一个(对于您不知道有多少参数的情况)
...继续
3).bind
像其他两个一样工作,除了不是触发函数,它制作函数的副本,其中this
总是指向同一个对象,而不是每次调用函数时都计算。
var sayBob = sayName.bind(bob);
sayBob(); // Bob
Bind 的工作原理是这样的:
function bind_this (new_this) {
var func = this;
return function () {
func.call(new_this);
}
}
function sayName () {
console.log(this.name);
}
sayName.bind_this = bind_this;
var sayBob = sayName.bind_this(bob);
sayBob(); // Bob
为了让论点正确,还有更多的事情要做,但这就是想法。
4)只需将您想要使用的功能设置为您想要使用它的事物的属性......
var bob = { name : "Bob" };
function sayName () { console.log(this.name); }
bob.sayName = sayName;
bob.sayName(); // Bob
你有它......这些是使用方法this
如果使用new
then 则this
指向一个新对象。
如果您使用.call
.apply
.bind
或设置函数作为对象的属性,则this
指向您设置的对象。
如果您不执行上述任何一项操作,请this
指向window
。
函数是嵌套 6 深还是在全局范围内都没有关系。这些是你的选择。
想象一下我的 Point2D 看起来像这样:
var Point2D = function (x, y) {
var this = undefined;
if (new) { this = {}; }
else if (called) { this = called; }
else { this = window; }
this.x = x;
this.y = y;
this.setX = function (x) {
this = undefined;
if (new) { this = {}; }
else if (called) { this = called; }
else { this = window; }
/* this function is set as a property of another object -- so it is "called", always */
this.x = x;
if (new) { return this; }
};
this.setY = function (y) { /* same as setX */ };
if (new) { return this; }
};
所有函数的内部,嵌套或非嵌套的工作,在引擎盖下......
所以现在,看着它,你应该看到它们之间的区别:
var obj = {};
var point = new Point2D(1, 3); // new object
var point2 = Point2D(2, 3); // point2 is empty and window gets the values
Point2D.call(obj, 5, 7); // obj is added to, instead of making a new object
所以现在,希望您了解以下内容:
var bob = {
name : "bob",
speak : function () {
var name = this.name; // bob
console.log(name + " is lower case.");
function uppercase () {
var window_name = this.name;
console.log(window_name + " is window.name.");
}
uppercase();
function working_uppercase () { console.log(this.name.toUpperCase()); }
working_uppercase.call(this);
}
};
如果你不明白为什么这是真的,那就相信我的话,相信我是对的,几年后,这将成为你的第二天性。
另一种解决方案可能是避免this
或谨慎使用它以避免混淆。
var Point2D = function (x, y) {
this.x = x;
this.y = y;
this.findMagnitude = function () {
return Math.sqrt(this.x * this.x
+ this.y * this.y);
};
};
var point = Point2D(3, 7);
哎呀!没有new
。
point; // undefined
window.findMagnitude; // function () { ... }
那么为什么不处理不会搞砸的功能呢?
var Point2D = function (x, y) {
var point = {
x : x,
y : y,
setX : function (x) { this.x = x; },
setY : function (y) { point.y = y; }
};
return point;
};
var point1 = Point2D(1, 3),
point2 = Point2D(2, 7);
我什this
至在其中一种方法上使用过,但是因为我是直接在对象上设置的,所以只要不将函数复制到其他地方或在回调中使用它就可以了。
另一个,我在...上使用了一个引用。该函数可以提供给其他对象,也可以作为返回值传递,或者异步调用,每次,它都会对完全相同的对象执行完全相同的操作,因为它引用了对象,而不是this
.