Javascript 使该关键字引用实例而不是窗口对象
在下面的代码中,我创建了一个名为Slates的对象,并向其添加了一些函数Javascript 使该关键字引用实例而不是窗口对象,javascript,oop,prototype,Javascript,Oop,Prototype,在下面的代码中,我创建了一个名为Slates的对象,并向其添加了一些函数 “严格使用”; 函数Slates(){ 这是帆布; 这个.ctx; 这是宽度; 这是身高; } Slates.prototype.init=函数(){ this.canvas=document.getElementById(“canvas”); this.ctx=this.canvas.getContext(“2d”); 这是resize(); }; Slates.prototype.resize=函数(){ this.w
“严格使用”;
函数Slates(){
这是帆布;
这个.ctx;
这是宽度;
这是身高;
}
Slates.prototype.init=函数(){
this.canvas=document.getElementById(“canvas”);
this.ctx=this.canvas.getContext(“2d”);
这是resize();
};
Slates.prototype.resize=函数(){
this.width=window.innerWidth;
this.height=window.innerHeight;
this.canvas.width=this.width;
this.canvas.height=this.height;
console.log(“调整大小”);
};
Slates.prototype.render=函数(){
this.ctx.clearRect(0,0,this.width,this.height);
this.ctx.fillStyle=“rgba(0,0100,5)”;
this.ctx.fillRect(0,0,this.width,this.height);
};
window.onload=函数(){
var slates=新slates();
slates.init();
window.onresize=slates.resize;
window.requestAnimationFrame(slates.render);
};
问题是当我将函数slates.render
作为回调传递到函数中时
例如window.requestAnimationFrame
关键字this
指的是window
对象,而不是Slates
实例,因此我得到一个
未捕获的TypeError:无法读取未定义的属性“clearRect”
如何修复此问题,使其引用对象的实例?以下是指向的链接。您可以使用,例如,
Function.prototype.bind
,它将返回一个函数,但该值为常量:
window.requestAnimationFrame(slates.render.bind(slates))
或者将此调用包装到另一个函数中:
window.requestAnimationFrame(function() { slates.render() })
例如,您可以使用
Function.prototype.bind
,该函数将返回一个函数,但该值为常量:
window.requestAnimationFrame(slates.render.bind(slates))
或者将此调用包装到另一个函数中:
window.requestAnimationFrame(function() { slates.render() })
L值和r值 在编程中,有两种表达式:l值(“l”表示左侧)和r值(“r”表示右侧)。l值是可以赋值的东西,而r值是我们可以赋值给其他东西的东西。例如,假设我们有以下HTML
<div id="my-div" style="background-color: blue;"></div>
然后我们可以使用myDiv.style.backgroundColor
作为l值(即为其分配某些内容)
或作为r值(分配/传递给其他对象):
当我们有一个像上面myDiv.style.backgroundColor
中那样的“点链”时,它在表达式中的值等于链中最后一个链接的值。因此,当我们在表达式中使用myDiv.style.backgroundColor
时,我们只是使用backgroundColor
。将其分配给新元素,例如newDiv
,不会在myDiv.style
和newDiv.style
之间创建任何类型的链接
同样,当您将slates.render
分配给window.onload
时,您只分配了render
功能-不再有任何与slates
的连接
你可能会想。。。好的,但是这个不应该是指向石板的链接吗?好吧,想想看,在渲染
函数中,您实际上从未为这个
分配过任何内容,对吗?你刚刚用过。语言引擎为您提供this
的值。JS中的普通变量/属性,例如slates
或slates.render
可以是l值或r值,具体取决于上下文。但是,this
关键字仅作为r值
有效。如果我们尝试直接分配给this
关键字,我们将看到如下错误:
错误表明我们已经知道,此
不是有效的l值。那么它的价值是从哪里来的呢
这让我们讨论了JS中的作用域,以及为什么这个在一个重要方面不同于其他变量
词汇范围(变量如何工作)
在JS中,变量是词汇范围的,这意味着函数调用中变量的值不是由调用的范围决定的,而是由函数定义的范围决定的
var x = {name: "outer"};
function y() {
var x = {name: "inner"};
return function() {
console.log(x.name);
};
}
var z = y(); // z is a function here
z(); // logs "inner", not "outer" because JS is lexically scoped
在本例中,我们定义了一个函数y
,它本身返回一个分配给z
的函数。当执行z
时,它确实执行console.log(x.name)
,但问题是。。。它应该指哪个x
?如果JS是动态作用域,那么我们可能希望它打印“outer”,因为这是与变量z
在同一“作用域”中定义的x
。但事实并非如此。它打印“inner”,因为JS是词汇范围,这意味着x
等于定义时在范围内的x
var x = {name: "outer"};
function y() {
var x = {name: "inner"};
return function() {
console.log(x.name);
};
}
var z = y(); // z is a function here
z(); // logs "inner", not "outer" because JS is lexically scoped
动态范围(该关键字如何工作)
如果this
关键字与JS中的其他变量一样在词汇范围内,那么您文章中的代码就可以工作了。但事实并非如此。JS中的普通变量是词汇范围,而this
关键字不是词汇范围。它具有动态范围。这意味着它的值不取决于定义函数的上下文,而是取决于函数执行的上下文。您在什么上下文中执行它?窗口对象!如果您想象加载事件的调用方式类似于window.onload()
,那么这一点就更清楚了
事实上,这就是我们想要的行为。因为如果在按钮上设置了单击事件,则可能会执行以下操作:
var inputBox = document.getElementById("my-input-box");
function myFunc() {
alert("Uh oh, you typed " + this.value);
}
inputBox.onchange = myFunc;
这是同样的行为。有点让人困惑的是,window
也是默认的this
值。(更多信息见下文)
除了一些例外(包括new
操作符和bind
、call
和apply
方法),在JS中将这个
值传递给函数的唯一方法是对对象(如t)调用它
object.method(); // this now refers to object within `method`
Ball.prototype.kick = function() {
this.touch();
this.move();
console.log(this);
}
myBall = new Ball();
kickBall = ball.kick.bind(myBall); // returns a new function, doesn't affect the original ball.kick
kickBall(); // myBall
window.setTimeout(myBall.kick, 1000); // window
window.onload = function() {
slates.render(); // this works because doing obj.method() passes obj as a this value to method
};