JS中的面向对象是在语言的发展中经历了汇编语言,面向过程,面向对象语言。面向过程是亲力亲为,所有代码自己写。而面向对象是对现实世界的模拟,JS准确说是基于对象的语言,不像Java有类的概念。面向对象注重的结果,是抽象出现实世界的世间万物的特征,行为加以描述。
一、了解创建对象的三种方式
创建对象三种方式:
1 字面量的方式,只能描述一个对象。
2 调用系统的构造函数,是字面量方式的升级。
3 自定义构造函数方式
<script type="text/javascript">
// 创建对象难点三种方式 一种是
//自定义
function Person(){
name=""
age=""
findPeople:function(){
}
}
//字面量形式
var person={
name:"",
age:"",
area""
findPerson:function(){
console.log("我的世界");
}
//引用构造函数的实例
var person=new Object();
person.name=""
person.findPeople=function(){
}
//自定义构造函数
function Person(){
this.name=""
this.age=""
this.findPeoson=function(){
}
}
}
</script>
二、自定义构造函数的时候做了什么事
*new person 的时候做了几件事
* 1.开辟空间存储对象
* 2.把this设置为当前的对象
* 3.设置属性和方法的值
* 4.把this对象返回
三、工厂函数和自定义函数的区别
function createObject(name,age) {
var obj=new Object();
obj.name=name;
obj.age=age;
obj.sayHi=function () {
console.log("您好");
};
return obj;
}
console.log(Object);
var obj=new Object();
console.log(obj); console.log(createObject);
共同点:都是函数,都可以创建对象,都可以传入参数
*
* 工厂模式:
* 函数名是小写
* 有new,
* 有返回值
* new之后的对象是当前的对象
* 直接调用函数就可以创建对象
*
* 自定义构造函数:
* 函数名是大写(首字母)
* 没有new
* 没有返回值
* this是当前的对象
* 通过new的方式来创建对象
function Person(name,age) {
this.name=name;
this.age=age;
this.sayHi=function () {
console.log("您好");
};
}
console.log(Person);
四、构造函数和实例对象的关系
面向对象的思想是先抽象出现实世界的东西。比如说人,抽象出人的构造函数,人的每个个体不一样,就是一种实例化的过程。面向对象先抽象出人的属性和行为,age name sex 行为:eat 然后通过new实例化对象。一句话:实例对象是通过构造函数来创建,构造函数用来创建实例对象的。实例对象的构造器是指向Person的,结果是true,所以,这个实例对象per就是通过Person来创建的。
五、痛点通过构造函数创建对象需要每次在内存中开辟空间,占据原本内存。如何实现数据的共享,不用每次实例化对象才能调用方法和属性。引入原形的概念。原形解决的问题是:数据共享和节省内存空间。
function Person (name,age) {this.name=name;
}
Person.prototype.eat=function(){
console.log("吃大白菜");
}
六、构造函数和实例对象中的原形
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.dir(p1);
console.dir(p2);
console.dir(Person);
p1.__proto__.eat();
console.log(p1.__proto__==Person.prototype
* 实例对象中有__proto__这个属性,叫原型,也是一个对象,这个属性是给浏览器使用,不是标准的属性----->__proto__----->可以叫原型对象
* 构造函数中有prototype这个属性,叫原型,也是一个对象,这个属性是给程序员使用,是标准的属性------>prototype--->可以叫原型对象
*
* 实例对象的__proto__和构造函数中的prototype相等--->true
* 又因为实例对象是通过构造函数来创建的,构造函数中有原型对象prototype
* 实例对象的__proto__指向了构造函数的原型对象prototype
七、面向对象编程的体会
或许刚开始感觉用DOM操作元素做出事件非常简单代码很少,但是遇到大的项目。还是面向对象简单。编辑一次,可以多次使用,这对不同的的对象可以任意改变,样式。只知道如何使用就可以。比如在最后升级版中,我们封装的事件源可以任意改变,把btn换成p元素。json 中的数据可以按照自己的意愿改变更加方便快捷。
效果是点击按钮改变的是div的颜色。
<input type="button" value=" 现实效果“ id="btn"/>
<div id="div"></div>
<script src="conmmon.js"></script>
<script>
//传统写法
document.getElementById("btn").οnclick=function(){
document.getElementById("div").style.backgroundColor="yellow";
}
//使用初级的面向对象的思想编程
function ChangeStyle(btnId,dvId,color){
this.btnId=btnId;
this.dvId=dvId;
this.color=color;
}
ChangeStyle.prototype.init=function(){
var that=this;
this.btnId.οnclick=function(){
that.dvId.style.backgroundColor=that.color;
}
}
var cs=new ChangeStyle("btn","dv","yellow");
cs.init();
//面向对象高级
function ChangeStyle(btn,dv,json){
this.btnobj=btn;
this.dvobj=dv;
this.json=json;
}
ChangeStyle.prototype.init=function(){
var that=this;
this.btn.οnclick=function(){
for(var key in json){
that.dvobj.style.[key]=that.json[key];
}
}
}
var json={"width":"500px","height":"500px","backgroundColor": "blue", "opacity": "0.2"};
var cs=new ChangeStyle(my$("btn"),my$("dv"),json);
cs.init();// 调用方法
八、构造函数和实例对象、原形对象之间的关系
构造函数可以用来实例化对象,构造函数的属性prototype指向的是构造函数的原形对象。
构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数
构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的
实例对象中都有_prototype_原形对象指向的是构造函数中protorype原形对象
记住:凡是函数都有:prototype原形对象的属性 凡是对象都有:——proto——原形对象。
由于函数也是对象所以函数中存在:_protype_原形对象。所以函数中存在两个原形对象:prototype/_protype_.
但是,对象不一定是函数,比如:Math对象中就没有prototype
八、原形中的语法
1.原形中字面量语法 会改变constructor的指向。所以需要手动修改student的 constructor 的指向。
这时候在控制台上的:person.prototype中就有了constructor
<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);
2.原形对象中的方法是可以相互访问
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();//
九、实例对象的属性和方法的层层搜索机制
实例对象调用方法的时候先在实例中查找,如果没有找到就到。原形中查找。如果原形中还是找到。就会报错。
<script>
function Person(age,sex) {
this.age=age;//年龄
this.sex=sex;
this.eat=function () {
console.log("构造函数中的吃");
};
}
Person.prototype.sex="女";
Person.prototype.eat=function () {
console.log("原型对象中的吃");
};
var per=new Person(20,"男");
console.log(per.sex);//男
per.eat();
console.dir(per);
十、为内置对象添加原形方法
我们所使用的内置对象中的方法大多是通过原形的形式创建,供给我们使用的。所以牛人都是创建对象的,我们一般水平的是使用对象的。
JS中的内置对象,
对象是包含一系列无序属性和方法的集合。他们有很多的方法和属性
Arguments 函数参数集合
Array 数组
Boolean 布尔对象
Date 日期时间
Error 异常对象
Function 函数构造器
Math 数学对象
Number 数值对象
Object 基础对象
RegExp 正则表达式对象
String 字符串对象
String.prototype.myReverse=function () {
for(var i=this.length-1;i>=0;i--){
console.log(this[i]);
}
};
var str="abcdefg";
str.myReverse();
十一、把局部变量变成全局变量
了解一个小知识:自调用函数。自调用函数的实现规则
function fun(){
console.log("我是函数“);
}
fun();调用函数。我们知道这个函数的调用中的fun是函数名。
上面的调用形式等于 (function fun(){console.log("我是函数");})(); //用匿名函数,省略函数名就可以了。记住后面分号一定需要加上。
自调用函数只能够执行一次,就是一次性函数,在声明的同时就直接调用了。
(function (win) {
var num=10;//局部变量
//js是一门动态类型的语言,对象没有属性,点了就有了
win.num=num;
})(window);
console.log(num);
//如何把局部变量变成全局变量? //把局部变量给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;
})(window);
//实例化随机数对象
var rm=new Random();
//调用方法产生随机数
console.log(rm.getRandom(0,5));
//全局变量
</script>
十二、案例 随机小方块
分析:1.首先是小球是随机产生的,所以我们需要一个函数或者说是方法封装随机数的产生。并且需要让其变成全局对象。
2.产生小方块对象,思考它应该具备的属性和方法。宽,高、颜色。然后需要把它添加入map 中,创建元素去装 小方块对象。
3.设置小方块的样式。
4.产生随机位置。
5.实例化对象。每次刷新都会使得小方块的位置变化。
<!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.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);
};
//产生随机位置
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>