什么是类与对象?那么什么又是面向对象?
先来解释一下什么是类。类,中文的释义是很多相同事物的综合,例如:人类、书类、汽车类、笔……,这些都很明显,意思就是把许多相同事物或者类似事物综合在一起统归为一个类,就好比说到书类,我们很自然的脑海中就会浮现一本书的大致模样。而 JavaScript 中的类亦是如此,有数组类(Array)、字符串类(String)、日期类(Date)……这些都是官方定义的类,在实际开发当中,程序员也需要把项目中的众多相同的类似的属性与方法定义成无数的类,帮助我们完成需求。
再来解释一下什么是对象。对象,中文的释义是目标、描写或写实的特指的人或物,例如:人的名字:李xx,王xx、书的名字:语文,数学、笔:铅笔,毛笔等;……很明显,所谓的对象我们可以暂且理解为是某个类特指的实例,这个特指的实例且具有它所在类的相同属性,就好比铅笔,笔的属性是什么呢:能书写。而在 JavaScript 中的对象我们也可以暂时理解为就是某个类的具象(实例),且这个对象有着和它所在类相同的属性和方法,比如:var arr1 =new Array();
这里的 arr1 就是通过类 Array 创造或者说定义出来的对象; var d1 = new Date();
这里的 d1 是用类 Date 创造(定义)出来的对象。
那么什么又是面向对象呢?从我们对类和对象的解释基本可以看出 JavaScript 中的类与对象和生活中的类与对象何其相似;所谓程序来源于生活,人之所以发明了计算机并为它赋予了计算机的属性(能计算能画画能编程等等)同时也赋予了操作计算机的方法(通过鼠标的移动点击,键盘的字符输入等),就是为了它能够更好的帮助我们人类去实现我们希望达成的某种需求(小到计算数值,大到完成一个项目的开发),目的、方法都很明确,这些都是靠着我们人类的思维去想去做,所以面向对象,我们可以简单的理解为面向着一个实例一个具象,去想,要怎么做,所以面向对象的思想其实就是我们人类的思维去想去做。例如生活中的面向对象,打个比方我们需要建造一个公寓,公寓在这里就是一个房子类的具象(实例),那么建房子我们需要怎么做呢?首先我们需要去构思,房子要建多大啊,是什么样的结构啊,要建多少层啊等等;构思完了我们就需要去行动去做,第一步打地基啊,第二步开始盖啊……(具体怎么建房子我不是很熟悉,只能大概的表达个意思,抱歉)。而程序中的面向对象,我们也是需要构思完成这个项目需要哪些类,这些个类有什么属性和方法,然后行动,用类创造(定义)出对象,调用方法,第一步用哪个类创建哪个对象,调用哪个方法,第二步又用哪个类调用哪个对象,调用哪个方法……
所以,面向对象完成一个项目基本可以暂时分为:
1)先定义好无数个类(属性和方法);
2)再写步骤;
3)最后创建对象,调用方法,最终完成项目。
那么,既然已知面向对象就是面向着一个实例一个具象,去想,去做,去怎么做的话,前提之下我们是不是得有这么一个实例这么一个具象(也就是对象)呢?接下来我们先简单介绍一下创建对象的几种方式(从最初的创建方式到其最终的相对较完善的创建方式):
Object是一切类的根类。具体创建方法如下:
var person = new Object(); //创建一个空对象
// 给空对象增加属性
person.name = "张三疯";
person.sex = "男";
person.age = 20;
// 给空对象增加方法
person.eat = function(){
}
优点: 简单,创建对象少或者一个对象时,可以使用。
缺点:1)、代码复用性差;
2)、不知道对象属于哪个类型,或者说,哪些对象是同一个类型;
其实json创建对象和 new Object()创建对象本质是一样的,仅仅只是写法上的不同,具体创建方法如下:
var person = {
name:"张三疯",
sex:"男",
eat:function(){
}
}
// 给对象person增加一个属性
person.age = 20;
优点: 简单,创建对象少或者一个对象时,可以使用。
缺点:1)、代码复用性差;
2)、不知道对象属于哪个类型,或者说,哪些对象是同一个类型;
把创建对象的代码放在函数里,所有的属性作为参数传入,具体创建方法如下:
function createPerson(name,sex){
var t = new Object();
t.name = name;
t.sex = sex;
t.eat = function(){
}
return t;
}
优点:代码复用性好;
缺点:不知道对象属于哪个类型,或者说,哪些对象是同一个类型。
最终比较好的解决方案,用在复杂的项目中。
构造函数把工厂(普通)函数进行进一步的简化,不需要程序再写重复的代码(如new Object()和return),具体创建方法如下:
function Person(name,sex){
this.name = name;
this.sex = sex;
this.eat = function(){
}
}
构造函数和普通函数的区别:
1)写法上,构造函数名首字母大写
2)省略了 new Object(); 在预编译会自动加上
3)省略了 return this; 在预编译会自动加上
4)调用构造函数时,使用 new运算符,其实,当js编译器发现调用函数时,前面有new运算符,那么,编译器就会自动在函数的第一个行增加 this = new Object(); 在最后一行增加return this,反之,则js编译器就会把它当作普通函数调用,即,不增加 new Object 和 return this;
优点:1)、代码复用性好,因为构造函数就是特殊的函数而已。
2)、构造函数的方式创建的对象,能够确定对象属于哪个类型(instanceof),或者说,哪些对象是同一个类型;
再次重申类与对象的观念:
1)为什么要再次重申这个观念呢?因为看到这里的伙伴们就会有疑问:
2)疑问:你看,你写的创建对象的第四个用构造函数的方法明明就是创建了一个类!!!还说是创建对象,前面又解释说类就是分门别类的类,对象就是实例(具象),这不是有矛盾吗?
解答:确实,构造函数呢是类,也是对象!解释一下:
首先,因为函数是对象,不知道大家是否还记得创建函数的时候的一种写法:var fn = function(){}
,其实这种写法是省略了new的关键字的一种写法,原写法是var fn = new Function()
,所以大家很容易就可以看出这就是创建对象的第一种写法啊。所以,因为构造函数也是函数,那么构造函数就也是对象了。
其次,构造函数是类,定义好了一个构造函数,通过构造函数又可以 new 出一个新的对象,那么自然而然的这个构造函数也就是该对象(实例)的类了。
所以,构造函数既是类,也是对象。
<script>
// 定义一个类
function ball(size, left1, top1, color, step, directionLeft, directionTop, timeSpace){
// 创建其相关属性
this.dom = null;
this.size = size;
this.left1 = left1;
this.top1 = top1;
this.color = color;
this.step = step;
this.directionLeft = directionLeft;
this.directionTop = directionTop;
this.timeSpace = timeSpace;
// 创建其 html结构 方法
this.createDom = function(){
this.dom = document.createElement('div');
this.dom.style.cssText = `
width: ${this.size}px;
height: ${this.size}px;
background: ${this.color};
border-radius: 100%;
position: absolute;
left: ${this.left1}px;
top: ${this.top1}px;
`;
document.body.appendChild(this.dom);
}
// 创建其 运动 方法
this.go = function(){
setInterval(
() => {
this.left1 = this.left1 + this.directionLeft * this.step;
this.top1 = this.top1 + this.directionTop * this.step;
// 横向
let clientWidth = document.documentElement.clientWidth || document.body.clientWidth;
let scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
if(this.left1 + this.size > clientWidth + scrollLeft){
this.left1 = clientWidth + scrollLeft - this.size;
this.directionLeft = -1;
}else if(this.left1 < scrollLeft){
this.left1 = scrollLeft;
this.directionLeft = 1;
}
// 纵向
let clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if(this.top1 + this.size > clientHeight + scrollTop){
this.top1 = clientHeight + scrollTop - this.size;
this.directionTop = -1;
}else if(this.top1 < scrollTop){
this.top1 = scrollTop;
this.directionTop = 1;
}
this.dom.style.left = this.left1 + 'px';
this.dom.style.top = this.top1 + 'px';
},this.timeSpace)
}
// 调用方法
this.createDom();
this.go();
}
var box = document.getElementById('box');
var box2 = document.getElementById('box2');
// 页面加载完成时触发
window.onload = function(){
// 创建对象 b1
let b1 = new ball(50, 100, 100, 'red', 1, 1, 1, 5)
// 创建对象 b2
let b2 = new ball(50, 50, 80, 'blue', 2, -1, -1, 5)
}
</script>
效果图如下:
具体实现代码如下:
<script>
// 定义类
function Enlarge(box, obj){
// 创建其相关属性
this.box = box;
let defaultObj = {
width: 100,
height: 120,
multiple: 2,
backgroundColor: 'black',
left: 0,
top: 0,
img: 'img/b1.jpg'
}
for(let key in obj){
defaultObj[key] = obj[key];
}
for(let key in defaultObj){
this[key] = defaultObj[key];
}
this.createDom();
this.addEvent();
}
// 创建其 html结构 方法
Enlarge.prototype.createDom = function(){
let htmlStr = '';
// 放大镜
htmlStr += `
${this.width}px;
height: ${this.height}px;
background: ${this.backgroundColor};
opacity: .5;
position: absolute;
left: ${this.left}px;
top: ${this.top}px;
display: none;
">
`;
boxWidth = this.box.offsetWidth;
boxHeight = this.box.offsetHeight;
htmlStr += `
${this.width * this.multiple}px;
height: ${this.height * this.multiple}px;
border: 1px solid black;
position: absolute;
left: ${boxWidth + 30}px;
top: 0;
background: url(${this.img});
background-size: ${boxWidth * this.multiple}px ${boxHeight * this.multiple}px;
background-position: -${this.left * this.multiple}px -${this.top * this.multiple}px;
display: none;
">
`;
this.box.innerHTML = htmlStr;
}
// 创建其 事件 方法
Enlarge.prototype.addEvent = function(){
let enlargeBox = this.box.lastElementChild.previousElementSibling;
let showBox = this.box.lastElementChild;
this.box.onmouseover = function(){
enlargeBox.style.display = 'block';
showBox.style.display = 'block';
}
this.box.onmouseout = function(){
enlargeBox.style.display = 'none';
showBox.style.display = 'none';
}
let boxOffsetLeft = this.box.offsetLeft;
let boxOffsetTop = this.box.offsetTop;
this.box.onmousemove = (event) => {
let e = event || window.event;
this.left = e.pageX - boxOffsetLeft - this.width / 2;
this.top = e.pageY - boxOffsetTop - this.height / 2;
if(this.left < 0){
this.left = 0;
}else if(this.left + this.width > boxWidth){
this.left = boxWidth - this.width;
}
if(this.top < 0){
this.top = 0;
}else if(this.top + this.height > boxHeight){
this.top = boxHeight - this.height;
}
enlargeBox.style.left = this.left + 'px';
enlargeBox.style.top = this.top + 'px';
showBox.style.backgroundPosition = `-${this.left * this.multiple}px -${this.top * this.multiple}px`;
}
}
window.onload = function(){
let box = document.getElementById('box');
// 创建对象
new Enlarge(box, {
width: 100,
img: 'img/b2.jpg'
});
}
</script>
链接: https://blog.csdn.net/Zhuangvi/article/details/105333420.