迷惑的this
目标
完善 js/index.js
中的 handle
函数中的 TODO 部分,实现以下功能:
- 为输入框(即 this.inputEl
)绑定 input
事件,当输入框的值发生变化时,调用已经提供的 handleInput
方法进行搜索处理,注意 handleInput
方法调用时的 this
指向应为 search
对象本身。
const data = [
{ id: 1, content: "明日方舟" },
{ id: 2, content: "明朝" },
{ id: 3, content: "明天会更好" },
{ id: 4, content: "明星" },
{ id: 4, content: "m" },
{ id: 5, content: "mi" },
{ id: 6, content: "min" },
{ id: 7, content: "ming" },
];
const search = {
inputEl: null,
listEl: null,
data: [],
init(options) {
this.initData(options.el);
this.handle();
},
initData(el) {
//获取页面上的输入框
this.inputEl = el.querySelector("input");
//获取页面上的显示项的ul标签
this.listEl = el.querySelector(".search-list");
},
//事件处理函数
handle() {
// TODO:待补充代码
this.inputEl.addEventListener('input', this.handleInput.bind(this));
},
// 搜索处理函数
handleInput(e) {
const value = e.target.value;
// 使用定时器模拟 ajax 发送请求,data 接收数据
setTimeout(() => {
this.data = !!value
? data.filter((val) => val.content.indexOf(value) !== -1)
: [];
// 渲染搜索结果到页面上的列表
this.render();
});
},
render() {
// 根据得到的数组转化为 li 标签,并插入到 .search-list 元素(ul标签)内
const template = this.data.reduce(
(prev, next) => prev + `<li>${next.content}</li>`,
""
);
this.listEl.innerHTML = template;
},
};
search.init({
el: document.getElementById("app"),
});
1.this
handleInput
函数会被调用,并且它的上下文(即this
的值)会被绑定到当前的search
对象实例上。
this
指向的是search
对象,而不是输入框元素。这样做的目的是为了方便在事件处理函数中访问和操作对象的属性和方法,而无需每次都使用对象名来调用它们。
因为事件监听器默认情况下的 this 是触发事件的DOM元素(在这里是inputEl
),而不是包含这个函数的对象。通过使用bind(this)
,我们确保了在handleInput
函数内部,this
指向的是search
对象,而不是输入框元素。
2. .bind(this):
bind
是一个JavaScript函数的方法,用于改变函数的上下文(即this
的值)。在这里,它确保handleInput
方法在执行时,其上下文是当前的类实例。这意味着this
在handleInput
方法中指的是当前的类实例search,而不是而不是输入框元素。
贪吃蛇
找到 index.js
文件中的 nextStep
函数,完成函数中的 TODO 部分:
- 根据当前蛇的移动方向(
this.direction
)以及蛇身块的大小(this.size
),计算新的蛇头位置,更新蛇身坐标数组 (this.snakeBody
),即可实现蛇的正确移动。蛇的移动和增加蛇的长度代码已提供。
蛇身坐标示例如下:
[{ left: 2, top: 0 }, { left: 1, top: 0 }, { left: 0, top: 0 }]`
蛇的身体是由多个坐标点组成的,每个坐标点包含了 left
和 top
属性,分别表示在游戏界面中的水平和垂直位置,第一个坐标表示当前蛇头的位置。
思路:
1. 首先通过snakeHead变量,拿到蛇头的位置
2. 接着定义了一个新的蛇头
3.利用switch、case,形参是蛇的移动方向this.direction,分别是上下左右
4.由题目中给出的蛇的坐标表达,我们将新的坐标赋值给蛇头
5. 然后利用unshift和pop的配合,模拟蛇的移动(前多一个后少一个)
// 移动蛇的头部
nextStep() {
// TODO:待补充代码
//this指向Snake
const snakeHead = this.snakeBody[0]; //拿到蛇头的位置
let newHead;
switch (this.direction) {
case 'right':
newHead = { left: snakeHead.left + this.size, top: snakeHead.top };
break;
case 'down':
newHead = { left: snakeHead.left, top: snakeHead.top + this.size };
break;
case 'left':
newHead = { left: snakeHead.left - this.size, top: snakeHead.top };
break;
case 'up':
newHead = { left: snakeHead.left, top: snakeHead.top - this.size };
break;
}
//更新蛇头的位置
//使用 `unshift` 方法,我们将新的蛇头位置添加到 `this.snakeBody` 数组的开始位置。
this.snakeBody.unshift(newHead);
//* 使用 `pop` 方法,我们从 `this.snakeBody` 数组的末尾删除一个元素。这两个操作结合起来,实际上是在移动蛇的位置,而不是增加其长度。蛇的头部移动到新的位置,而尾部则被删除,从而模拟了蛇的移动效果。
this.snakeBody.pop();
}
6. 更新蛇的位置除了上面的方法,还可以利用for循环
for (let i = 1; i < this.snakeBody.length; i++) {
this.snakeBody[i].top = tempList[i - 1].top;
this.snakeBody[i].left = tempList[i - 1].left;
}
这个循环从蛇身的第二个部分(索引为1)开始,并遍历到蛇身的最后一个部分。对于每个部分,它都会设置新的 top
和 left
属性值,这些值来自 tempList
中对应部分的位置。
简单来说,这个循环确保蛇身的每一部分都跟随其前一部分的位置移动。这样,当蛇头移动时,整个蛇都会跟随它移动