JS中的面向对象/定时器/BOM
一.JS中的面向对象
1.创建对象的几种常用方式
(1).使用Object或对象字面量创建对象
(2).工厂模式创建对象
(3).构造函数模式创建对象
(4).原型模式创建对象
2.使用Object或对象字面量创建对象
JS中最基本创建对象的方式
<script type="text/javascript"> //最基本创建对象的方式 var student = new Object(); student.name = "wahaha"; student.age = "18"; student.fav = function(){ alert(this.name); } student.fav() </script>
student对象创建完毕,拥有name和age两个属性,分别赋值为"wahaha","18"
如果你嫌这种方法有种封装不实的感觉,来一个对象字面量方式方式创建对象
<script type="text/javascript"> //对象字面量的方式创建 var student = { name : "wahaha", age : 18, fav:function(){ alert(this.name) } }; student.fav(); </script>
这样看起来似乎已经完美了,但是我们又会发现一个严重的问题:当我们需要创建同类的student1,student2,...时,我们不得不得将以上的代码重复n次

var sutdent1 = { name : "哇哈哈", age : 18 }; var sutdent2 = { name : "乳娃娃", age : 18 }; ... var sutdentn = { name : "爽歪歪", age : 18 };
于是就出现了"工厂模式"
3.工厂模式创建对象
JS中没有类的概念,那么我们不妨就使用一种函数将以上对象创建过程封装起来以便于重复调用,同时可以给出特定的接口来初始化对象
<script type="text/javascript"> //工厂模式 function createStudent(name,age){ var obj = new Object; obj.name = name; obj.age = age; return obj; } var student1 = createStudent("娃哈哈",18); var student2 = createStudent("爽歪歪",18); var student3 = createStudent("乳娃娃",18); </script>
这样一来我们就可以高枕无忧了,但是贪婪的人类总是不满足于现状:我们不仅希望"产品"的生产可以像工厂车间一般源源不断,我们还想知道生产的产品究竟是哪种类型的;于是,我们同时又定义了"生产"水果对象的createFruit()函数:
<script type="text/javascript"> //水果对象 function createFruit(name, color){ var obj = new Object; obj.name = name; obj.color = color; return obj; } var v1 = createStudent("优酸乳", 18); var v2 = createFruit("苹果", "红色"); </script>
对于以上代码创建的对象v1,v2,我们有instanceof操作符去检查,他们统统都是Object类型,我们的当然不满足于此,我们希望v1是Student类型的,而v2是Fruit类型的,为了实现这个目标,我们可以用自定义构造函数的方法来创建对象
4.构造函数模式创建对象
在上面创建Object这样的原生对象的时候,我们就使用过其构造函数:
var obj = new Object();
在创建原生数组Array类型对象时也使用过其构造函数:
var arr = new Array(10); //构造一个初始长度为10的数组对象
在进行自定义构造函数创建对象之前, 我们首先了解一下构造函数和普通函数有什么区别
(1).实际上并不存在创建构造函数的特殊语法,其与普通函数唯一的区别在于调用方法,对于任意函数,使用new操作符调用,那么它就是构造函数; 不使用new操作符调用,那么它就是普通函数
(2).按照惯例,我们约定构造函数名以大写字母开头 ,普通函数以小写字母开头,这样有利于显性区分二者,例如上面的new Array(), new Object()
(3).使用new操作符调用构造函数时,会经历: ①创建一个新对象; ②将构造函数作用域赋给新对象(使this指向该新对象); ③执行构造函数代码; ④返回新对象; 四个阶段
OK,了解了构造函数和普通函数的区别以后,我们使用构造函数将工厂模式的函数重写,并添加一个方法属性:
function Student(name, age) { this.name = name; this.age = age; this.alertName = function(){ alert(this.name) }; } function Fruit(name, color) { this.name = name; this.color = color; this.alertName = function(){ alert(this.name) }; }
这样我们再分别创建Student和Fruit的对象:
var v1 = new Student("娃哈哈", 18); var v2 = new Fruit("苹果", "红色");
这时我们再来用instanceof操作符来检测以上对象类型就可以区分出Student以及Fruit了:
alert(v1 instanceof Student); //true alert(v2 instanceof Student); //false alert(v1 instanceof Fruit); //false alert(v2 instanceof Fruit); //true alert(v1 instanceof Object); //true 任何对象均继承自Object alert(v2 instanceof Object); //true 任何对象均继承自Object
这样我么就解决了工厂模式无法区分对象类型的尴尬,那么使用构造方法来创建对象是否已经完美了呐?使用构造器函数通常在JS中我们来创建对象
我们会发现Student和Fruit对象中共有同样的方法,当我们进行调用的时候这无疑是内存的消耗
我们完全可以在执行该函数的时候再这样做,办法是将对象方法移到构造函数外部:
function Student(name, age) { this.name = name; this.age = age; this.alertName = alertName; } function alertName() { alert(this.name); } var stu1 = new Student("easy1", 20); var stu2 = new Student("easy2", 20);
在调用stu1.alertName()时,this对象才被绑定到stu1上
我们通过将alertName()函数定义为全局函数,这样对象中的alertName属性则被设置为指向该全局函数的指针。由此stu1和stu2共享了该全局函数,解决了内存浪费的问题; 但是,通过全局函数的方式解决对象内部共享的问题,终究不像一个好的解决方法。如果这样定义的全局函数多了,我们想要将自定义对象封装的初衷便几乎无法实现了。更好的方案是通过原型对象模式来解决
5.原型的模式创建对象
原型链甚至原型继承,是整个JS中最难的一部分也是最不好理解的一部分,这里由于本人才疏学浅就不解释那么多了,有兴趣的老铁可以去研究研究,更加有助于你以后的前端JS的面试
function Student() { this.name = 'easy'; this.age = 20; } Student.prototype.alertName = function(){ alert(this.name); }; var stu1 = new Student(); var stu2 = new Student(); stu1.alertName(); //easy stu2.alertName(); //easy alert(stu1.alertName == stu2.alertName); //true 二者共享同一函数
<script> function Person(name,age) { this.name = name; this.age = age; } // Person.prototype 它是person的父类 // 原型 prototype Person.prototype.showName = function() { // this指的是person console.log(this.name) } var p1 = new Person('alex',18); console.log(p1); p1.showName(); </script>
二.定时器
在JS中定时器分为两种:①.setTimeout(); ②.setInterval()
1.setTimeout()
只在指定时间后执行一次

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>定时器</title> </head> <body> <button id="start">开启定时器</button> <button id="close">关闭定时器</button> <div id="box"></div> <script type="text/javascript"> var time = 0; document.getElementById("start").onclick = function(){ //未来数据交互的时候,如果数据阻塞了,可以考虑加一个一次性定时器来处理 time = setTimeout(function(){ console.log("娃哈哈"); },2000); console.log("爽歪歪"); } document.getElementById("close").onclick = function(){ clearTimeout(time); } </script> </body> </html>
2.setInterval()
在指定时间为周期循环执行

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>定时器</title> <style type="text/css"> #box{ width: 100px; height: 100px; background-color: azure; } </style> </head> <body> <button id="start">开启定时器</button> <button id="close">关闭定时器</button> <div id="box"></div> <script type="text/javascript"> //clearInterval var count = 0; var time = 0; //开启定时器 document.getElementById("start").onclick = function(){ var oDiv = document.getElementById("box"); clearInterval(time); time = setInterval(function(){ count += 10; oDiv.style.marginLeft = count + "px"; },50) } //关闭定时器 document.getElementById("close").onclick = function(){ clearInterval(time) } </script> </body> </html>
两种方法根据不同的场景和业务需求择而取之
对于这两种方法,需要注意的是如果要求在每隔一个固定的时间间隔后就精准的执行某动作,那么最后使用setInterval,而如果不想由于连续调用产生互相干扰的问题,尤其是每次函数的调用需要繁重的计算以及很长的处理时间,那么最好使用setTimeout
三.BOM
1.BOM的介绍
JavaScript基础分为三个部分:
ECMAScript: JavaScript的语法标准,包括变量, 表达式, 运算符, 函数, if语句, for语句等..
DOM: 文档对象模型,操作网页上的元素的API, 比如让盒子移动, 变色, 轮播图等..
BOM: 浏览器对象模型, 操作浏览器部分功能的API,比如让浏览器自动滚动
2.什么是BOM
BOM: Browser Object Model, 浏览器对象模型
BOM的结构图:
从上图可以看出:
window对象是BOM的顶层(核心)对象,所有对象都是通过它延伸出来的,也可称为window的子对象
DOM是BOM的一部分
window对象:
window对象JavaScript中的顶级对象
全局变量,自定义函数也是window对象的属性和方法
window对象下的属性和方法调用时, 可以省略window
3.下面说一下BOM的常见内置方法和对象
(1).弹出系统对话框
比如说, alert(1)是window.alert(1)的简写, 因为他是window的子方法
系统对话框有三种:
alert(); //不同浏览器中的外观是不一样的 confirm(); //兼容不好 prompt(); //不推荐使用
(2).打开窗口,关闭窗口
①.打开窗口:
window.open(url,target)
参数解释:
url: 要打开的地址
target: 新窗口的位置, 可以是: _blank, _self, _parent 父框架

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <!--行间的js中的open() window不能省略--> <button onclick="window.open('https://www.luffycity.com/')">路飞学城</button> <button>打开百度</button> <button onclick="window.close()">关闭</button> <button>关闭</button> </body> <script type="text/javascript"> var oBtn = document.getElementsByTagName('button')[1]; var closeBtn = document.getElementsByTagName('button')[3]; oBtn.onclick = function(){ open('https://www.baidu.com') //打开空白页面 // open('about:blank',"_self") } closeBtn.onclick = function(){ if(confirm("是否关闭?")){ close(); } } </script> </html>
4.location对象
window.location可以简写成location。location相当于浏览器地址栏,可以将url解析成独立的片段
(1).location对象的属性
href: 跳转
hash: 返回url中#后面的内容, 包含#
host: 主机名, 包括端口
hostname: 主机名
pathname url: 中的路径部分
protocol: 协议, 一般都是http, https
search: 查询字符串

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div>点击</div> </body> <script type="text/javascript"> var div = document.getElementsByTagName('div')[0]; div.onclick = function(){ location.href = "http://baidu.com"; //点击div,跳转到百度 // window.open("http://baidu.com","_blank"); //方式二 } </script> </html>

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> </body> <script type="text/javascript"> //5秒后自动跳转到百度 setTimeout(function(){ location.href = "http://baidu.com"; },5000) </script> </html>
提示:有时候,当我们访问一个不存在的网页时,会提示5秒后自动跳转到指定页面,此时就可以用到location
(2).location对象的方法
location.reload(): 重新加载

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> </body> <script type="text/javascript"> //3秒之后让网页整个刷新 window.location.reload(); },3000) </script> </html>
5.navigator对象
window.navigator 的一些属性可以获取客户端的一些信息
userAgent:系统,浏览器
platform:浏览器支持的系统, win/mac/Linux
示例:
console.log(navigator.userAgent);
console.log(navigator.platform);
6.history对象
(1).后退:
history.back()
history.go(-1): 0是刷新
(2).前进:
history.forward()
history.go(1)
用的不多,因为浏览器中已经自带了这些功能的按钮