1、实例对象和构造函数之间的关系:
- 实例对象是通过构造函数来创建的---创建的过程叫实例化
- 如何判断对象是不是这个数据类型?
- 1) 通过构造器的方式 实例对象.构造器==构造函数名字
- 2) 对象 instanceof 构造函数名字
尽可能的使用第二种方式来识别,为什么?原型讲完再说。
2、构造函数创建对象引发的问题
<script>
function Person(name,age) {
this.name=name;
this.age=age;
this.eat=function () {
console.log("今天吃红烧土豆");
}
}
per1.eat();
per2.eat();
//不是同一个方法
console.log(per1.eat==per2.eat);
for(var i=0;i<100;i++){
var per=new Person("嘎嘎",20);//创建100个对象
per.eat();//创建100个方法。非常浪费内存
}
// 可以采用以下方法查看文件结构,会发现它们分别调用一次eat方法,不是使用的同一个方法。
// console.dir(per1);
// console.dir(per2);
</script>
由此可以看出,使用构造函数创建对象,有多少个对象就调用几次eat方法,使用的不是同一个方法,非常占用内存。
怎么解决?--让它们调用同一个方法。
//先把eat这个方法封装为一个函数
function myEat() {
console.log("吃大榴莲");
}
//var myEat=10;这里不行了。会造成命名冲突
function Person(name,age) {
this.name=name;
this.age=age;
//用在这里,相当于调用
this.eat=myEat;
}
var per1=new Person("小白",20);
var per2=new Person("小黑",30);
console.dir(per1);
console.dir(per2);
console.log(per1.eat==per2.eat);
这种方法有缺陷,当我再定义一个var myEat=10;的时候,会造成命名冲突。
怎么解决?--通过原型来解决---------数据共享,节省内存空间(作用之一)
<script>
function Person(name,age) {
this.name=name;
this.age=age;
}
//通过【原型】来添加方法,解决数据共享,节省内存空间
Person.prototype.eat=function () {
console.log("吃凉菜");
};
var p1=new Person("小明",20);
var p2=new Person("小红",30);
console.log(p1.eat==p2.eat);//true
// 结果是true 可见是同一个方法了
</script>
查看文件结构,可见实例对象中根本没有eat方法,但是能够使用,这是为什么?
console.dir(p1);
console.dir(p2);
* 原型是什么?
实例对象中有__proto__这个属性,叫原型。也是一个对象,这个属性是给浏览器使用,不是标准的属性。
----->__proto__----->可以叫原型对象
构造函数中有prototype这个属性,叫原型。也是一个对象,这个属性是给程序员使用,是标准的属性。
------>prototype--->可以叫原型对象
* 实例对象的__proto__和构造函数中的prototype相等--->true
* 又因为实例对象是通过构造函数来创建的,构造函数中有原型对象prototype
* 实例对象的__proto__指向了构造函数的原型对象prototype。
什么时候把方法写到原型里?--数据共享
window是对象
document是属性,document也是一个对象
write()是方法
window.document.write("哈哈");
对象.style.color=值;
例子:感受面向过程和面向对象的编程思想
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初级的面对对象思想</title>
<style>
div {
width: 300px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<div>
<button id="btn">确定</button>
</div>
<div id="div"></div>
<p>初级的面对对象思想--
按钮是一个对象,div是一个对象,颜色是一个属性
</p>
<script>
// 创建一个构造方法,传进去三个参数,把它们变成对象
function ChangeStyle(btnID,divID,color) {
// 按钮对象
this.btnobj=document.getElementById(btnID);
// div对象
this.divobj=document.getElementById(divID);
// 颜色对象
this.color=color;
}
// 数据共享来改变div的背景颜色--把方法添加到原型里
ChangeStyle.prototype.init=function(){
// console.log(this);//这条语句就是为了证明this就是实例对象--就是当前对象
// 想实现点击按钮,改变div的背景颜色。
// that变量用于获取到这个this,为什么看下面
var that=this;
this.btnobj.onclick=function(){
// 这里写 “this.onclick=function()”也可以 ,所以
//要注意:这里的this和上面 console.log(this);的this不是同一个this
// 这里的this=this.btnobj
// 上面的this是cs
// 如果我想要获取到div,不能在这下面写this.div
// 如果写了就相当于 this.btnobj.div,这显然不对
// 那怎么写?--先在这个大括号外把那个this获取一下:var that=this;。
that.divobj.style.backgroundColor="that.color";
}
}
// 创建的这个init方法怎么用?--实例化对象
var cs=new ChangeStyle("btn","div","yellew");
// 调用方法
cs.init();//=>输出ChangeStyle(实例对象)
// 所以console.log(this);的this就是实例对象--就是当前对象
</script>
</body>
</html>
上面console.log(this);得到结果如下图,这是一个实例对象(如果是构造方法,会得到prototype)。
上面初级版本有点弱,在构造函数里传递的是ID。
现在换成对象。--可以改变使用少量代码改变多个属性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
div {
width: 300px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<input type="button" value="显示效果" id="btn"/>
<div id="dv"></div>
<script src="common.js"></script>
<script>
function ChangeStyle(btnObj, dvObj, json) {
this.btnObj = btnObj;
this.dvObj = dvObj;
this.json = json;
}
ChangeStyle.prototype.init = function () {
//点击按钮,改变div多个样式属性值
var that = this;
this.btnObj.onclick = function () {//按钮
for (var key in that.json) {
that.dvObj.style[key] = that.json[key];
}
};
};
//实例化对象
var json = {"width": "500px", "height": "800px", "backgroundColor": "blue", "opacity": "0.2"};
var cs = new ChangeStyle(my$("btn"), my$("dv"), json);
cs.init();//调用方法
</script>
</body>
</html>
注意上面例子里为什么要var that =this;
因为按钮事件的this就是这个按钮,即:按钮事件的this=this.btnobj=按钮。
复习原型
<script>
// 1、构造函数
function Person(name,age){
this.name=name;
this.age=age;
}
// 2、通过原型添加方法
Person.prototype.sayHi=function(){
console.log("打招呼,您好!");
};
// 3、实例化对象,调用
var per=new Person("Bella","22");
per.sayHi();
</script>
3、构造函数,原型对象,实例对象之间的关系
* 构造函数可以实例化对象。
* 构造函数中有一个属性叫prototype,是构造函数的原型对象。
* 构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数。
* 实例对象的原型对象(__proto__)指向的是该构造函数的原型对象。
* 构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的。
4、利用原型共享数据
什么样的数据是需要写在原型中? --需要共享的数据可写在原型中。
属性需要共享,方法也需要共享。
不需要共享的数据写在构造函数中,需要共享的数据写在原型中。
step1:构造函数:
function Student(name,age,sex) {
this.name=name;
this.age=age;
this.sex=sex;
}
step2:如果(使用原型对象),所有学生身高188,所有人的体重都是55。所有学生都要每天写500行代码,所有学生每天都要吃一个10斤的西瓜:
// 原型对象
Student.prototype.height="188cm";
Student.prototype.weight="55kg";
Student.prototype.write=function(){
console.log("每天写500行代码");
}
Student.prototype.eat=function(){
console.log("每天都要吃一个10斤的西瓜");
}
step3:实例化对象,并初始化.
var stu=new Student("bella",22,"男");
console.dir(Student);
console.dir(stu);
console.log(stu.write);
5、原型的简单写法
可以把添加到原型中的属性和方法集中写在原型中,但是这样会丢失构造器(原因是这样看student,是不知道他的构造函数是谁),解决办法是手动修改构造器的指向。
<script>
function Student(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
//简单的原型写法
Student.prototype = {
//手动修改构造器的指向
constructor:Student,
height: "188",
weight: "55kg",
study: function () {
console.log("学习好开心啊");
},
eat: function () {
console.log("我要吃好吃的");
}
};
var stu=new Student("段飞",20,"男");
stu.eat();
stu.study();
console.dir(Student);
console.dir(stu);
</script>
6、原型对象中添加方法
原型中的方法是可以相互访问的。
//原型中的方法,是可以相互访问的
//原型对象中的方法,可以相互调用
function Animal(name,age) {
this.name=name;
this.age=age;
}
//原型中添加方法
Animal.prototype.eat=function () {
console.log("动物吃东西");
this.play();
};
Animal.prototype.play=function () {
console.log("玩球");
this.sleep();
};
Animal.prototype.sleep=function () {
console.log("睡觉了");
};
var dog=new Animal("小苏",20);
dog.eat();
7、实例对象使用的属性和方法的层次搜索
function Animal(age,sex){
this.sex=sex;
this.age=age;
this.eat=function(){
console.log("构造函数中的吃")
};
}
// Animal
var ani=new Animal(20,"男");
console.log(ani.sex);//==》男
function Animal(age,sex){
this.sex=sex;
this.age=age;
this.eat=function(){
console.log("构造函数中的吃")
};
}
// 在这里添加一个原型,值为女
Animal.prototype.sex="女";
var ani=new Animal(20,"男");
console.log(ani.sex);//结果还是男
原因是它先从实例对象中找,构造函数中的属性方法都变成实例对象中的属性。
如果在构造函数中的sex属性去掉,只在原型中添加sex=女,最后输出sex,结果变为女:
function Animal(age){
// this.sex=sex;
this.age=age;
this.eat=function(){
console.log("构造函数中的吃")
};
}
// 在这里添加一个原型,值为女
Animal.prototype.sex="女";
var ani=new Animal(20);
console.log(ani.sex);//==》女
总结:实例对象用到的属性方法先在实例对象中找,没有的到原型中找。
8、为内置对象添加原型方法
我们能否为系统的对象的原型中添加方法,相当于在改变源码。
// 我希望字符串中有一个倒序字符串的方法
String.prototype.myReverse=function () {
for(var i=this.length-1;i>=0;i--){
console.log(this[i]);
}
};
var str="abcdefg";
str.myReverse();
//为Array内置对象的原型对象中添加方法
Array.prototype.mySort=function () {
for(var i=0;i<this.length-1;i++){
for(var j=0;j<this.length-1-i;j++){
if(this[j]<this[j+1]){
var temp=this[j];
this[j]=this[j+1];
this[j+1]=temp;
}//end if
}// end for
}//end for
};
var arr=[100,3,56,78,23,10];
arr.mySort();
console.log(arr);
String.prototype.sayHi=function () {
console.log(this+"哈哈,我又变帅了");
};
//字符串就有了打招呼的方法
var str2="小杨";
str2.sayHi();
</script>
9、局部变量变成全局变量
函数的自调用--一次性函数--声明的同时,直接调用。
如何把局部变量变成全局变量?-- 把局部变量给window就可以了。
<script>
//通过自调用函数产生一个随机数对象,在自调用函数外面,调用该随机数对象方法产生随机数
(function (window) {
//产生随机数的构造函数
function Random() {
}
//在原型对象中添加方法
Random.prototype.getRandom = function (min,max) {
return Math.floor(Math.random()*(max-min)+min);
};
//把Random对象暴露给顶级对象window--->使外部可以直接使用这个对象
window.Random=Random;//把 Random 给了Random这个 属性
})(window);
//实例化随机数对象
var rm=new Random();
//调用方法产生随机数
console.log(rm.getRandom(0,5));
//全局变量
</script>
复习:
- 面向过程和面向对象都是编程的思想,方式不一样
- 面向过程:凡事都是亲力亲为,所有的代码都要自己写,每一步都要很清楚,注重的是过程
- 面向对象:执行者成为指挥者,只要找对象,然后让对象做相关的事情,注重的是结果
- 面向对象的特性:封装,继承,多态
- 封装:就是代码的封装,把一些特征和行为封装在对象中.
- 面向对象的编程思想:
- 根据需求,抽象出相关的对象,总结对象的特征和行为,把特征变成属性,行为变成方法,
- 然后定义(js)构造函数,实例化对象,通过对象调用属性和方法,完成相应的需求.---编程的思想。
- 对象:具体特指的某个事物,有特征(属性)和行为(方法),对象可以看成是一无序属性的集合
- 如何创建对象?
通过调用new Object(),还有字面量{},自定义构造函数
- 创建对象的方式
- 调用系统Object()----->创建出来的对象都是Object类型的,不能很明确的指出这个对象是属于什么类型
- 字面量的方式{}----->只能创建一个对象(一次只能创建一个)
- 自定义构造函数的方式---工厂模式创建对象-----自定义构造函数(优化后的工厂模式)
- 自定义构造函数创建对象:4件事
- 在内存中申请一块空闲的空间,存储创建的对象
- this就是当前实例化的对象
- 设置对象中的属性和方法(为对象添加属性和方法,为属性和方法赋值)
- 把创建后的对象返回
- 都是需要通过new的方式
- 什么是原型?
- 构造函数中有一个属性prototype,是原型,程序员使用的
- 实例对象中有一个属性__proto__,是原型,浏览器使用的,不是很标准的,
- 实例对象中的__proto__指向的就是该实例对象中的构造函数中的prototype
- 构造函数中的prototype里面的属性或者方法,可以直接通过实例对象调用
- 正常的写法:实例对象.__proto__才能访问到构造函数中的prototype中的属性或者方法
per.__proto__.eat();//__proto__不是标准的属性
per.eat();
- 原型就是属性,而这个属性也是一个对象
Person.prototype--->是属性
Person.prototype.属性或者Person.ptototype.方法()
- 本身在构造函数中定义的属性和方法,当实例化对象的时候,实例对象中的属性和方法都是在自己的空间中存在的。
如果是多个对象,这些属性和方法都会在单独的空间中存在,浪费内存空间,
所以,为了数据共享,把想要节省空间的属性或者方法写在原型对象中,达到了数据共享,实现了节点内存空间。
- 原型的作用之一:数据共享,节省内存空间
- 原型的写法:
- 构造函数.prototype.属性=值
- 构造函数.prototype.方法=值---->函数.prototype,函数也是对象,所以,里面也有__proto__
- 实例对象.prototype-------->实例对象中没有这个属性,只有__proto__(暂时的)
- 多个属性方法的简单原型的写法:用大括号一起括起来
缺陷:--->新的知识点---->原型直接指向{}---->就是一个对象,没有构造器
构造函数.prototype={
把共享的属性和方法都放在大括号里;
切记:如果这这种写法,要把构造器加上
};
- 通过原型为内置对象添加原型的属性或者方法----->原因:
系统的内置对象的属性和方法可能不满足现在需求,所以,可以通过原型的方式加入属性或者方法,为了方便开发。
- 为内置对象的原型中添加属性和方法,那么这个内置对象的实例对象就可以直接使用了。
String.prototype.方法=匿名函数;
var str="哈哈";
str.方法();---->实例对象可以直接调用原型中的属性或者方法
function Person(age) {
this.age=age;
}
Person.prototype.sayHi=function () {
};
var p=new Person(10);
p.sayHi();
10、案例:随机小方块(贪吃蛇里的食物)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
.map{
width: 800px;
height: 600px;
background-color: #CCC;
position: relative;
}
</style>
</head>
<body>
<div class="map"></div>
<script src="common.js"></script>
<script>
//产生随机数对象的
(function (window) {
function Random() {
}
Random.prototype.getRandom=function (min,max) {
return Math.floor(Math.random()*(max-min)+min);
};
//把局部对象暴露给window顶级对象,就成了全局的对象
window.Random=new Random();
})(window);//自调用构造函数的方式,分号一定要加上
//产生小方块对象
(function (window) {
//console.log(Random.getRandom(0,5));
//先获取地图,选择器的方式来获取元素对象
var map=document.querySelector(".map");
//食物的构造函数(实例对象由构造函数创建)
function Food(width,height,color) {
this.width=width||20;//默认的小方块的宽
this.height=height||20;//默认的小方块的高
//横坐标,纵坐标
this.x=0;//横坐标随机产生的
this.y=0;//纵坐标随机产生的
this.color=color;//小方块的背景颜色
this.element=document.createElement("div");//创建小方块的元素
}
//初始化小方块的显示的效果及位置---显示地图上
Food.prototype.init=function (map) {
//设置小方块的样式
var div=this.element;//div对象
div.style.position="absolute";//脱离文档流
div.style.width=this.width+"px";
div.style.height=this.height+"px";
div.style.backgroundColor=this.color;
//把小方块加到map地图中
map.appendChild(div);
this.render(map);
};
//产生随机位置(render是传递的意思)
Food.prototype.render=function (map) {
//随机产生横纵坐标
var x=Random.getRandom(0,map.offsetWidth/this.width)*this.width;//坐标点*宽
var y=Random.getRandom(0,map.offsetHeight/this.height)*this.height;
this.x=x;
this.y=y;
var div=this.element;
div.style.left=this.x+"px";
div.style.top=this.y+"px";
};
//实例化对象
var fd=new Food(20,20,"green");
fd.init(map);
console.log(fd.x+"===="+fd.y);
})(window);
</script>
</body>
</html>
11、贪吃蛇案例
<!-- 三个对象:游戏、蛇、食物
怎么玩?-用户按下上下左右箭头--需要监听键盘按键-来让蛇按照什么方向走。
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>贪吃蛇案例</title>
<style>
.map {
width: 800px;
height: 600px;
background-color: #CCC;
position: relative;
/* 蛇和食物都是要在地图上运动,所以它们是脱离了文档流,地图是父元素,蛇和食物是子元素
所以父元素position:relative; */
}
</style>
</head>
<body>
<!--画出地图,设置样式-->
<div class=" map"></div>
<script>
//自调用函数----食物的
(function () {
var elements = [];//用来保存每个小方块食物的
//食物就是一个对象,有宽,有高,有颜色,有横纵坐标,先定义构造函数,然后创建对象
function Food(x, y, width, height, color) {
//横纵坐标
this.x = x || 0;
this.y = y || 0;
//宽和高
this.width = width || 20;
this.height = height || 20;
//背景颜色
this.color = color || "green";
}
//为原型添加初始化的方法(作用:在页面上显示这个食物)
//因为食物要在地图上显示,所以,需要地图的这个参数(map--就是页面上的.class=map的这个div)
Food.prototype.init = function (map) {
//先删除这个小食物
//外部无法访问的函数
remove();
//创建div
var div = document.createElement("div");
//把div加到map中
map.appendChild(div);
//设置div的样式
div.style.width = this.width + "px";
div.style.height = this.height + "px";
div.style.backgroundColor = this.color;
//先脱离文档流(不脱离,不能随机坐标)
div.style.position = "absolute";
//随机横纵坐标
this.x = parseInt(Math.random() * (map.offsetWidth / this.width)) * this.width;
this.y = parseInt(Math.random() * (map.offsetHeight / this.height)) * this.height;
div.style.left = this.x + "px";
div.style.top = this.y + "px";
//把div加入到数组elements中
elements.push(div);
};
//私有的函数---删除食物的
function remove() {
//elements数组中有这个食物
for (var i = 0; i < elements.length; i++) {
var ele = elements[i];
//找到这个子元素的父级元素,然后删除这个子元素
ele.parentNode.removeChild(ele);
//再次把elements中的这个子元素也要删除
elements.splice(i, 1);
}
}
//把Food暴露给Window,外部可以使用
window.Food = Food;
}());
//自调用函数----食物end
//自调用函数---小蛇
(function () {
var elements = [];//存放小蛇的每个身体部分
//小蛇的构造函数
function Snake(width, height, direction) {
//小蛇的每个部分的宽
this.width = width || 20;
this.height = height || 20;
//小蛇的身体
this.body = [
{x: 3, y: 2, color: "red"},//头
{x: 2, y: 2, color: "orange"},//身体
{x: 1, y: 2, color: "orange"}//身体
];
//方向
this.direction = direction || "right";
}
//为原型添加方法--小蛇初始化的方法
Snake.prototype.init = function (map) {
//先删除之前的小蛇
remove();//===========================================
//循环遍历创建div
for (var i = 0; i < this.body.length; i++) {
//数组中的每个数组元素都是一个对象
var obj = this.body[i];
//创建div
var div = document.createElement("div");
//把div加入到map地图中
map.appendChild(div);
//设置div的样式
div.style.position = "absolute";
div.style.width = this.width + "px";
div.style.height = this.height + "px";
//横纵坐标
div.style.left = obj.x * this.width + "px";
div.style.top = obj.y * this.height + "px";
//背景颜色
div.style.backgroundColor = obj.color;
//方向暂时不定
//把div加入到elements数组中----目的是为了删除
elements.push(div);
}
};
//为原型添加方法---小蛇动起来
Snake.prototype.move = function (food, map) {
//改变小蛇的身体的坐标位置
var i = this.body.length - 1;//2
for (; i > 0; i--) {
this.body[i].x = this.body[i - 1].x;
this.body[i].y = this.body[i - 1].y;
}
//判断方向---改变小蛇的头的坐标位置
switch (this.direction) {
case "right":
this.body[0].x += 1;
break;
case "left":
this.body[0].x -= 1;
break;
case "top":
this.body[0].y -= 1;
break;
case "bottom":
this.body[0].y += 1;
break;
}
//判断有没有吃到食物
//小蛇的头的坐标和食物的坐标一致
var headX=this.body[0].x*this.width;
var headY=this.body[0].y*this.height;
//判断小蛇的头的坐标和食物的坐标是否相同
if(headX==food.x&&headY==food.y){
//获取小蛇的最后的尾巴
var last=this.body[this.body.length-1];
//把最后的蛇尾复制一个,重新的加入到小蛇的body中
this.body.push({
x:last.x,
y:last.y,
color:last.color
});
//把食物删除,重新初始化食物
food.init(map);
}
}
;//删除小蛇的私有的函数=============================================================================
function remove() {
//删除map中的小蛇的每个div,同时删除elements数组中的每个元素,从蛇尾向蛇头方向删除div
var i = elements.length - 1;
for (; i >= 0; i--) {
//先从当前的子元素中找到该子元素的父级元素,然后再弄死这个子元素
var ele = elements[i];
//从map地图上删除这个子元素div
ele.parentNode.removeChild(ele);
elements.splice(i, 1);
}
}
//把Snake暴露给window,外部可以访问
window.Snake = Snake;
}());
//自调用函数---游戏对象================================================
(function () {
var that = null;//该变量的目的就是为了保存游戏Game的实例对象-------
//游戏的构造函数
function Game(map) {
this.food = new Food();//食物对象
this.snake = new Snake();//小蛇对象
this.map = map;//地图
that = this;//保存当前的实例对象到that变量中-----------------此时that就是this
}
//初始化游戏-----可以设置小蛇和食物显示出来
Game.prototype.init = function () {
//初始化游戏
//食物初始化
this.food.init(this.map);
//小蛇初始化
this.snake.init(this.map);
//调用自动移动小蛇的方法========================||调用了小蛇自动移动的方法
this.runSnake(this.food, this.map);
//调用按键的方法
this.bindKey();//========================================
};
//添加原型方法---设置小蛇可以自动的跑起来
Game.prototype.runSnake = function (food, map) {
//自动的去移动
var timeId = setInterval(function () {
//此时的this是window
//移动小蛇
this.snake.move(food, map);
//初始化小蛇
this.snake.init(map);
//横坐标的最大值
var maxX = map.offsetWidth / this.snake.width;
//纵坐标的最大值
var maxY = map.offsetHeight / this.snake.height;
//小蛇的头的坐标
var headX = this.snake.body[0].x;
var headY = this.snake.body[0].y;
//横坐标
if (headX < 0 || headX >= maxX) {
//撞墙了,停止定时器
clearInterval(timeId);
alert("游戏结束");
}
//纵坐标
if (headY < 0 || headY >= maxY) {
//撞墙了,停止定时器
clearInterval(timeId);
alert("游戏结束");
}
}.bind(that), 150);
};
//添加原型方法---设置用户按键,改变小蛇移动的方向
Game.prototype.bindKey=function () {
//获取用户的按键,改变小蛇的方向
document.addEventListener("keydown",function (e) {
//这里的this应该是触发keydown的事件的对象---document,
//所以,这里的this就是document
//获取按键的值
switch (e.keyCode){
case 37:this.snake.direction="left";break;
case 38:this.snake.direction="top";break;
case 39:this.snake.direction="right";break;
case 40:this.snake.direction="bottom";break;
}
}.bind(that),false);
};
//把Game暴露给window,外部就可以访问Game对象了
window.Game = Game;
}());
//初始化游戏对象
var gm = new Game(document.querySelector(".map"));
//初始化游戏---开始游戏
gm.init();
//外部测试代码
// var fd = new Food();
// fd.init(document.querySelector(".map"));
// //创建小蛇
// var snake = new Snake();
// snake.init(document.querySelector(".map"));//先在地图上看到小蛇
//
//
//
// setInterval(function () {
// snake.move(fd, document.querySelector(".map"));
// snake.init(document.querySelector(".map"));
// }, 150);
// snake.move(fd, document.querySelector(".map"));//走一步
// snake.init(document.querySelector(".map"));//初始化---重新画一条小蛇(先删除之前的小蛇,把现在的小蛇显示出来)
// snake.move(fd, document.querySelector(".map"));
// snake.init(document.querySelector(".map"));
// snake.move(fd, document.querySelector(".map"));
// snake.init(document.querySelector(".map"));
// snake.move(fd, document.querySelector(".map"));
// snake.init(document.querySelector(".map"));
// snake.move(fd, document.querySelector(".map"));
// snake.init(document.querySelector(".map"));
// snake.move(fd, document.querySelector(".map"));
// snake.init(document.querySelector(".map"));
//
// snake.move(fd, document.querySelector(".map"));
// snake.init(document.querySelector(".map"));
// fd.init(document.querySelector(".map"));
// fd.init(document.querySelector(".map"));
// fd.init(document.querySelector(".map"));
// fd.init(document.querySelector(".map"));
//console.log(fd.x+"====>"+fd.y);
//console.log(fd.width);
</script>
</body>
</html>
12、键盘按下事件
<script>
//页面的任何的位置.按下键盘,获取按键的值
document.onkeydown=function (e) {
console.log(e.keyCode);//事件参数对象
};
</script>
13、原型链
14、原型 的指向是否可以改变