Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使该关键字引用实例而不是窗口对象_Javascript_Oop_Prototype - Fatal编程技术网

Javascript 使该关键字引用实例而不是窗口对象

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的对象,并向其添加了一些函数

“严格使用”;
函数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

};