第十五节 JS面向对象实例及高级
实例:面向对象的选项卡
把面向过程的程序,改写成面向对象的形式
原则:不能有函数套函数,但可以有全局变量
过程:
onload —— 改写成 构造函数,其中window.onload的功能是在页面加载时“初始换整个程序”,类似于构造函数——初始化整个对象
全局变量 —— 改写成 属性
函数 —— 改写成 方法
改错:this、时间、闭包、传参
对象与闭包:通过闭包传递this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>面向对象选项卡</title>
<style>
#div1 button{background: white;}
#div1 button.active{background: yellow;}
#div1 div{
width: 200px;
height: 200px;
background: #cccccc;
display: none;
}
</style>
<script>
// window.onload = function () {
// var oDiv = document.getElementById('div1');
// var aBtn = oDiv.getElementsByTagName('button');
// var aDiv = oDiv.getElementsByTagName('div');
//
// for (var i = 0; i < aBtn.length; i++) {
// aBtn[i].index = i;
//
// aBtn[i].onclick = function () {
// for (var i = 0; i < aBtn.length; i++) {
// aBtn[i].className = '';
// aDiv[i].style.display = 'none';
// };
// this.className = 'active';
// aDiv[this.index].style.display = 'block';
// }
// }
// }; // //此时我们要把上述语句改写为面向对象的代码
// var aBtn = null; //定义全局变量
// var aDiv = null; //定义全局变量
//
// window.onload = function () {
// var oDiv = document.getElementById('div1');
// aBtn = oDiv.getElementsByTagName('button');
// aDiv = oDiv.getElementsByTagName('div');
//
// for (var i = 0; i < aBtn.length; i++) {
// aBtn[i].index = i;
// aBtn[i].onclick = fnClick; //函数没有嵌套,只是调用
// }
// };
//
// function fnClick() {
// for (var i = 0; i < aBtn.length; i++) {
// aBtn[i].className = '';
// aDiv[i].style.display = 'none';
// }
// this.className = 'active'; //此处this表示当前被点击的那个按钮
// aDiv[this.index].style.display = 'block';
// } //在进行一次改写
window.onload = function () {
new TabSwitch('div1');
}; function TabSwitch(id) {
var _this = this; var oDiv = document.getElementById(id); this.aBtn = oDiv.getElementsByTagName('button');
this.aDiv = oDiv.getElementsByTagName('div'); for (var i = 0; i < this.aBtn.length; i++) {
this.aBtn[i].index = i;
// this.aBtn[i].onclick = this.fnClick; //此时fnClick已经不是一个函数了,而是一个方法
this.aBtn[i].onclick = function () {
_this.fnClick(this);
}; }
} TabSwitch.prototype.fnClick = function (oBtn) {
// alert(this); //[object HTMLButtonElement] for (var i = 0; i < this.aBtn.length; i++) {
this.aBtn[i].className = '';
this.aDiv[i].style.display = 'none';
}
oBtn.className = 'active'; //此时this代表当前的对象
this.aDiv[oBtn.index].style.display = 'block';
};
</script>
</head>
<body>
<div id="div1">
<button class="active">aaa</button>
<button>bbb</button>
<button>ccc</button>
<div style="display: block">111</div>
<div>222</div>
<div>333</div>
</div>
</body>
</html>
Json方式的面向对象
把方法包在一个Json里
<script>
// var json = {
// a:12,
// b:5,
// c:'abc',
// d:function () {alert('a');}
// };
// alert(json.a); //12
// json.d(); //a // var json = {
// a:12,
// show:function () {alert(this);} //此时this即指json
// };
// json.show(); //[object Object] //改写67.html,较67.html更加简单,但是缺点是不适合多个对象,比如再创建一个其他用户时,又需要在创建一个Json对象
var json = {
name:'haha',
qq:'123456789',
showName:function (){
alert('他的名字叫做:'+this.name);
},
showQQ:function () {
alert('他的QQ号为:'+this.qq);
}
};
json.showName();
json.showQQ();
</script>
有人称作——命名空间
<script>
var json = {}; //json中包含另外3个json json.common = {};
json.fx = {};
json.site = {}; //在不同的json里面写同一个名字的函数,并且不会相互冲突
json.common.getUser = function () {
alert('a');
};
json.fx.getUser = function () {
alert('b');
};
json.site.getUser = function () {
alert('c');
}; json.common.getUser();
json.fx.getUser();
json.site.getUser();
</script>
在公司里,把同一类方法,包在一起,既不会相互冲突,又方便查找
引用 :用“=”处理,和复制相似,但是两者指向的是同一个事物,而不是两个
<script>
// var arr1 = [1,2,3];
// var arr2 = arr1;
//
// arr2.push(4);
//
// alert(arr2); //返回:1,2,3,4
// alert(arr1); //返回:1,2,3,4
//原因是上面“arr2 = arr1;”语句知识把两个变量都指向了同一个数组,并不是指向两个不同的数组,此时该语句叫做“引用”,若想使其不相同,如下:
var arr1 = [1,2,3];
var arr2 = []; for (var i = 0; i<arr1.length; i++){
arr2.push(arr1[i]);
}
arr2.push(4); alert(arr2); //返回:1,2,3,4
alert(arr1); //返回:1,2,3
</script>
对象的继承
什么是继承:在原有的基础上,略作修改,得到一个新的类,并且不影响原有类的功能
<script>
function A() { //A的属性都写在函数内,构造函数
this.abc = 12;
} A.prototype.show = function () { //A的方法都现在原型上
alert(this.abc);
}; function B() {
A.call(this); //此时this表示new B() 即新建的B对象 用call来继承父级的属性
} // //继承属性
// var obj = new B();
// alert(obj.abc); //返回12 当B方法内没有定义“A.call(this);”时,返回的是undefined // //继承父级的属性我们可以用call,但是继承父级的方法我们用什么呢?如下:
// B.prototype = A.prototype;
// var obj = new B();
// obj.show(); //返回12 //但是问题在于当B存在自己的方法的时候时,如:
B.prototype = A.prototype; B.prototype.fn = function () {
alert('abc');
}; var objB = new B();
var objA = new B(); objA.fn(); //返回 abc 按理说不应该弹出该结果,因为B继承A;但是这样一来A B就互相继承了
</script>
拖拽和继承
面向对象的拖拽——改写原有拖拽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>面向对象的拖拽</title>
<style>
#div1{
width: 200px;
height: 200px;
background: red;
position: absolute;
}
</style>
<script>
// //面向过程的拖拽:
// window.onload = function () {
// var oDiv = document.getElementById('div1');
//
// oDiv.onmousedown = function (ev) {
// var oEvent = ev||event;
//
// var disX = oEvent.clientX-oDiv.offsetLeft;
// var disY = oEvent.clientY-oDiv.offsetTop;
//
// document.onmousemove = function (ev) {
// var oEvent = ev||event;
//
// oDiv.style.left = oEvent.clientX-disX+'px';
// oDiv.style.top = oEvent.clientY-disY+'px';
// };
// document.onmouseup = function () {
// document.onmousemove = null;
// document.onmouseup = null;
// };
// };
// }; //面向对象的拖拽:
//第一步:把所有的函数嵌套去掉
//第二步:把所有在多个函数中用到的变量,改为全局变量
// // var oDiv = null;
// var disX = 0;
// var disY = 0;
//
// function Drag(id) {
// oDiv = document.getElementById(id);
// oDiv.onmousedown = this.fnDown;
// };
//
// function fnDown(ev) {
// var oEvent = ev||event;
//
// disX = oEvent.clientX-oDiv.offsetLeft;
// disY = oEvent.clientY-oDiv.offsetTop;
//
// document.onmousemove = fnMove;
// document.onmouseup = fnUp;
// }
// function fnMove(ev) {
// var oEvent = ev||event;
//
// oDiv.style.left = oEvent.clientX-disX+'px';
// oDiv.style.top = oEvent.clientY-disY+'px';
// }
// function fnUp() {
// document.onmousemove = null;
// document.onmouseup = null;
// } //第三步:把“var oDiv = null;”注释掉,把对象的属性用this表示,即把div当做属性,然后合理添加this
// var oDiv = null;
window.onload = function () {
new Drag('div1');
}; function Drag(id) {
var _this = this; this.disX = 0;
this.disY = 0; this.oDiv = document.getElementById(id);
this.oDiv.onmousedown = function (ev) {
_this.fnDown(ev);
};
}; Drag.prototype.fnDown = function (ev) {
var _this = this; var oEvent = ev||event; this.disX = oEvent.clientX-this.oDiv.offsetLeft;
this.disY = oEvent.clientY-this.oDiv.offsetTop; document.onmousemove = function (ev) {
_this.fnMove(ev);
};
document.onmouseup = function (ev) {
_this.fnUp(ev);
};
};
Drag.prototype.fnMove = function (ev) {
var oEvent = ev||event; this.oDiv.style.left = oEvent.clientX-this.disX+'px';
this.oDiv.style.top = oEvent.clientY-this.disY+'px';
};
Drag.prototype.fnUp = function () {
document.onmousemove = null;
document.onmouseup = null;
}; //此时我们就可以把这些拖拽操作的方法,提取出来放到一个js文件中,方便之后需要使用只需 src引入 来使用即可
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
instanceof运算符:查看对象是否是某个类的实例
使用继承
限制范围的拖拽类
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>面向对象的拖拽</title>
<style>
#div1{
width: 200px;
height: 200px;
background: red;
position: absolute;
}
#div2{
width: 200px;
height: 200px;
background: green;
position: absolute;
}
</style>
<script src="74Drag.js"></script>
<script src="74limitDrag.js"></script>
<script>
window.onload = function () {
new Drag('div1');
new LimitDrag('div2');
};
</script>
</head>
<body>
<div id="div1">普通拖拽</div>
<div id="div2">范围受限制的拖拽</div>
</body>
</html>
function Drag(id) {
var _this = this; this.disX = 0;
this.disY = 0; this.oDiv = document.getElementById(id);
this.oDiv.onmousedown = function (ev) {
_this.fnDown(ev); return false; //拖拽一个物体时,防止另一个物体中的文字被选中
};
}; Drag.prototype.fnDown = function (ev) {
var _this = this; var oEvent = ev||event; this.disX = oEvent.clientX-this.oDiv.offsetLeft;
this.disY = oEvent.clientY-this.oDiv.offsetTop; document.onmousemove = function (ev) {
_this.fnMove(ev);
};
document.onmouseup = function (ev) {
_this.fnUp(ev);
};
};
Drag.prototype.fnMove = function (ev) {
var oEvent = ev||event; this.oDiv.style.left = oEvent.clientX-this.disX+'px';
this.oDiv.style.top = oEvent.clientY-this.disY+'px';
};
Drag.prototype.fnUp = function () {
document.onmousemove = null;
document.onmouseup = null;
};
74Drag.js
// 面向对象的继承
function LimitDrag(id) {
Drag.call(this, id); //继承属性
} for (var i in Drag.prototype) {
LimitDrag.prototype[i] = Drag.prototype[i];
} //覆盖掉其父级“Drag”的fnMove方法,并重写该方法
LimitDrag.prototype.fnMove = function (ev) {
var oEvent = ev||event; //重新写继承的父级方法
var l = oEvent.clientX-this.disX;
var t = oEvent.clientY-this.disY; if (l < 0) { //重新父级方法,使拖拽左右不可拖出可视区
l = 0;
} else if (l>document.documentElement.clientWidth-this.oDiv.offsetWidth) {
l = document.documentElement.clientWidth-this.oDiv.offsetWidth;
} this.oDiv.style.left = l+'px';
this.oDiv.style.top = t+'px';
};
74limitDrag.js
继承的好处体现在,我把父级的方法继承过来,也可以根据自己需要重写所继承父级方法中不存在的东西
构造函数伪装
属性的继承
原理:欺骗构造函数
call的使用
<script>
function show(a, b) {
alert('this是:'+this+'\na是:'+a+'\nb是:'+b);
} // show(12,5); //返回:this是:[object Window] a是:12 b是:5
// show.call(12, 5); //返回:this是:12 a是:5 b是:undefined 此时第一个参数即为this
show.call('haha', 12, 5); //this是:haha a是:12 b是:5
</script>
不使用“引用”的原型继承
<script>
function A() { //A的属性都写在函数内,构造函数
this.abc = 12;
} A.prototype.show = function () { //A的方法都现在原型上
alert(this.abc);
}; function B() {
A.call(this); //此时this表示new B() 即新建的B对象 用call来继承父级的属性
} // //继承属性
// var obj = new B();
// alert(obj.abc); //返回12 当B方法内没有定义“A.call(this);”时,返回的是undefined // //继承父级的属性我们可以用call,但是继承父级的方法我们用什么呢?如下:
// B.prototype = A.prototype;
// var obj = new B();
// obj.show(); //返回12 // //但是问题在于当B存在自己的方法的时候时,如:
// B.prototype = A.prototype;
//
// B.prototype.fn = function () {
// alert('abc');
// };
//
// var objB = new B();
// var objA = new B();
//
// objA.fn(); //返回 abc 按理说不应该弹出该结果,因为B继承A;但是这样一来A B就互相继承了, // 其实上述也是“引用”惹的祸,解决办法如下:复制,让他们指向不同的物体
for (var i in A.prototype) {
B.prototype[i] = A.prototype[i];
}
B.prototype.fn = function () {
alert('abc');
}; var objB = new B();
var objA = new B(); objA.fn();
</script>
原型链
方法的继承
原理:复制方法
覆盖原型和方法复制
系统对象
本地对象(非静态对象)
什么是本地对象:简单来说,需要进行实例化才能使用系统自带的类,叫做本地对象,常用非静态对象:Object、Function、Array、String、Boolean、Number、Date、RegExp(正则)、Error
内置对象(静态对象)
什么是本地对象:简单来说,凡是不需要new就能使用的对象就是内置对象,如Global(虚假对象,因为基本上用不到)、Math
var obj = new Math(); //错误用法,因为它属于静态对象
Math.ceil(); //正确使用方法
前两个对象不依赖于JS的执行环境,可以说是JS本身的对象
宿主对象(JS的运行环境)
由浏览器提供的对象,其实就是DOM、BOM;
Node.js运行环境是后台,所以其宿主对象就是后台的一系列对象。
第十五节 JS面向对象实例及高级的更多相关文章
- 第十四节 JS面向对象基础
什么是面向对象:在不需要知道它内部结构和原理的情况下,能够有效的使用它,比如,电视.洗衣机等也可以被定义为对象 什么是对象:在Java中对象就是“类的实体化”,在JavaScript中基本相同:对象是 ...
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
- 第四百一十五节,python常用排序算法学习
第四百一十五节,python常用排序算法学习 常用排序 名称 复杂度 说明 备注 冒泡排序Bubble Sort O(N*N) 将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮 ...
- 第三百八十五节,Django+Xadmin打造上线标准的在线教育平台—登录功能实现,回填数据以及错误提示html
第三百八十五节,Django+Xadmin打造上线标准的在线教育平台—登录功能实现 1,配置登录路由 from django.conf.urls import url, include # 导入dja ...
- 第三百一十五节,Django框架,CSRF跨站请求伪造
第三百一十五节,Django框架,CSRF跨站请求伪造 全局CSRF 如果要启用防止CSRF跨站请求伪造,就需要在中间件开启CSRF #中间件 MIDDLEWARE = [ 'django.midd ...
- centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课
centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件.目录属性 shell数组简单用法 $( ) 和$ ...
- centos lamp/lnmp阶段复习 以后搬迁discuz论坛不需要重新安装,只需修改配置文件即可 安装wordpress 安装phpmyadmin 定时备份mysql两种方法 第二十五节课
centos lamp/lnmp阶段复习 以后搬迁discuz论坛不需要重新安装,只需修改配置文件即可 安装wordpress 安装phpmyadmin 定时备份mysql两种方法 第二十五节 ...
- centos Linux系统日常管理2 tcpdump,tshark,selinux,strings命令, iptables ,crontab,TCP,UDP,ICMP,FTP网络知识 第十五节课
centos Linux系统日常管理2 tcpdump,tshark,selinux,strings命令, iptables ,crontab,TCP,UDP,ICMP,FTP网络知识 第十五节课 ...
- 风炫安全WEB安全学习第二十五节课 利用XSS键盘记录
风炫安全WEB安全学习第二十五节课 利用XSS键盘记录 XSS键盘记录 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源.所以xyz.com下的js脚本采用a ...
随机推荐
- Jmeter遇到打不开的问题
1.JDK的版本,一定版本的jmeter需要特定版本以上的JDK支持,比如此次运行的apache-jmeter-2.12,就需要JDK1.6以上的版本支持.我原来装的是JDK1.5,配置好JMETER ...
- Java是如何加载资源文件的?(源码解毒)
上文提到应老板要求开发一个测试工具能方便的加载存于文件中的测试参数,当时考虑既然是测试,把测试参数文件和测试类放在一起岂不是很方便,但是老板说:我的需求是你把测试参数文件放到统一文件夹下比如resou ...
- 最近发现一个php trim的bug
用trim 排除字符串两边的 “.”:你会发现“耀.”会出现编码错误问题,导致程序出现错误!代码如下: $a = "王者荣耀."; echo trim($a,".&quo ...
- FTP服务器匿名登录
ftp需要开通对匿名用户.本地用户.及虚拟用户的支持.并且特别对虚拟用户中的(stu.teacher.admin)分别授予不同的权限. 1.创建多层目录,然后挂载 2.配置yum源文件 3.安 ...
- Autofac之类型关联
前面的学习一直使用的是直接注册类型并不是Autofac已经依赖注入的主要使用方式,最佳的依赖注入与Autofac的使用方式,都是要结合面向接口(抽象)编程的概念的.推崇的是依赖于抽象而不是具体 pub ...
- 深度学习基础(四) Dropout_Improving neural networks by preventing co-adaptation of feature detectors
该笔记是我快速浏览论文后的记录,部分章节并没有仔细看,所以比较粗糙. 从摘要中可以得知,论文提出在每次训练时通过随机忽略一半的feature detectors(units)可以极大地降低过拟合.该方 ...
- Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/maven/cli/MavenCli : Unsupported major.minor version 51.0
原因:JDK版本不兼容.运行的Java Class文件采用高版本的JDK编译,然后在低版本的JRE环境中运行,有时会报此错误. 解决:1)升级JDK 2)调整Eclipse中Java Compiler ...
- Spring Boot web简介及原理 day04
一.SpringBoot创建web开发(三部曲) 1.快速构建SpringBoot项目,并以jar包的形式构建 2.选择对应的功能模块 (选定场景,配置少量的配置就可运行,不配置有默认值) 3.编写自 ...
- mysql本地安装
1.下载地址: https://downloads.mysql.com/archives/community/ 2.安装: 解压目录:D:\mysql\mysql-5.6.36-winx64 2.1. ...
- 【托业】【全真题库】TEST2-语法题
105 to do sth 不定时可充当形容词修饰名词 In an effort to reduce prices----为降低价格 106. 修饰比较级:far,much,even,still,a ...