修真院Web工程师零基础全能课html
本节课内容web
JavsScript对象编程
主讲人介绍数组
沁修,葡萄藤技术总监浏览器
项目经验丰富,擅长H5移动项目开发。编程语言
专一技术选型、底层开发、最佳代码实践规范总结与推广。函数
直播录屏版性能
传送门:https://v.qq.com/x/page/d0740...学习
课程大纲this
一、对象属性
1.1 什么是对象
1.2 对象那个的特征
1.3 访问对象的属性
1.4 枚举对象的属性
二、建立对象
2.1 经过键值对建立
2.2 使用new关键字加构造函数
2.3 ES5的新规范object.create()
三、原型与继承
3.1 prototype
3.2 prototype的相关属性
3.3 prototype的子方法
四、事件event
4.1 事件类型
4.2 注册事件处理程序
4.2.1 设置对象属性
4.2.2 设置html标签属性
4.2.3 addEventListener
4.2.4 attachEvent()
4.3 事件的冒泡与捕获
4.3.1 冒泡
4.3.2 捕获
4.3.3 应用
1.对象属性
1.1 什么是对象?
对象是事物,在现实世界中,一个球,一张桌子,一辆汽车都是对象。
对象就是具备可描述特征的事物,咱们能够用某种特定的方式去影响和操做它。
在JS中或者说在面向对象的编程语言中,对象是一系列属性和方法的组合。
一个属性包含属性名和属性值,这个值能够是任意类型的数据,也能够是个函数,这种状况下函数也被称为方法。
而在JS中,你遇到的全部东西几乎都是对象,那么咱们来了解一下对象的细节。
1.2 对象的特征?
对象有属性,也就是对象的特征,能够经过点符号来访问一个对象的属性。
objectName.propertyName;
若是把对象比做现实中的一个球,那这个球就是一个对象,拥有属性,有颜色有大小。这些能够这样表示:
var ball = new Object();
ball.color = “red";
ball.size = 12;
对象还有方法,方法用于定义对象的行为方式。
好比这个球可能有滚动的方法能够计算能滚多远,有弹跳的方法能够计算跳多高。
能够这样表示:
ball.roll = function() {
return this.size * laps
}
1.3 访问对象的属性
前面讲过咱们能够经过点符号来访问对象的属性,但若是是这样的状况,还能经过点符号访问对象的属性吗:
var ball = new Object();
ball.color = “red";
ball.size = 12;
var spec = “color”;
ball.spec ??
这里假设有一个变量spec,咱们须要经过这个变量spec来访问对象属性。
但若是用点符号将会访问ball的spec属性而后返回一个undefined,说明这里直接将spec当作了一个属性而不是变量。
若是咱们想要得到变量的值,来做为对象的属性那应该怎么作呢?
可使用方括号标记访问,这个标记法在属性名称那里是动态断定的,这样就能够经过存储在变量中的字符串来访问属性了:
ball[spec]; // red
1.4 枚举对象的属性
另外咱们能够经过for in循环语句来枚举对象的全部属性:
var ball = {color: “red”, size: 12, border: 2};
for (var prop in ball) {
console.log(“ball.” + prop + “=“ + obj[prop]);
}
// ball.color = red
// ball.size = 12
// ball.border = 2
// 若是但愿继承的属性不显示,那么能够用hasOwnProperty函数来过滤一遍
var bar = {a: 1, b: 2, c: 3};
function Foo() {
this.color = 'red';
}
Foo.prototype = bar;
var obj = new Foo();
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(prop);
}
}
也能够经过Object.keys(obj)的方法来返回一个属性名集合的数组:
var obj = {a: “123”, b: “das”, c: “web”};
console.log(Object.keys(obj)); // [“a”,”b”,”c”];
var arr = [“a”, “b”, “c”];
console.log(Object.keys(arr)); // [“0”,”1”,”2”];
2.建立对象
在JS中建立对象的方法一般有三种:
2.1 第一种
对象字面量的方式,使用花括号,直接经过键值对来建立:
var ball = {};
JS每次遇到这个表达式的时候都会建立一遍对象。
2.2 第二种
使用new关键字加构造函数:
var ball = new Object();
好比咱们想为球建立一个类型,而且将这类对象称为Ball,拥有一些属性,那么能够经过两步来建立对象:
1.建立一个构造函数Car来定义这个对象类型,首字母一般为大写,这是种习惯用法。
2.经过new建立对象实例:
function Ball(color, size, border) {
this.color = color;
this.size = size;
this.border = border;
}
var myBall = new Ball(“white”, 9, 1);
经过这样的方法能够建立许多实例,每一个实例之间互不影响。
2.3 第三种
ES5的新规范,Object.create(),它容许你为建立的对象选择其对象原型,不用定义一个构造函数
var Ball = {
color: “red”,
size: 12
}
var ball1 = Object.create(Ball);
这每一种建立方式继承的原型对象都不一样:
第一种的原型是Object.prototype
第二种的原型是构造函数的prototype属性
第三种的原型是传入的第一个参数,若是参数为空则原型为Object.prototype。
3.原型与继承
3.1 prototype
咱们先来看看这段代码:
var foo = {};
console.log(foo.toString()); //[Object Object]
这段代码意味着什么?咱们从一个空的对象中取出了一个属性?
事实上并非的,咱们将要了解一些JS对象的内部工做细节了:
每一个对象除了拥有本身的属性外,几乎都包含了一个原型prototype,继承的属性能够经过构造函数的prototype对象找到。
当咱们访问一个对象所不包含的属性时,它会从对象的原型中去搜索,原型的原型中去搜索,一直循着原型链往上直到搜索到或者到顶部为止。
说到prototype,其实每一个构造函数都有prototype这个属性,它指向另外个对象,而这个对象上全部的属性和方法都会被构造函数的实例所继承。
这就意味着咱们能够把不变的属性和方法,定义到prototype上去:
function Car(color) {
this.color = color;
}
var c1 = new Car(‘white’);
var c2 = new Car(‘red’);
Car.prototype.callColor = function() {
alert(this.color);
}
c1.callColor();
c2.callColor();
这里所生成的实例c1和c2,他们的callColor方法其实都是同一个内存地址,都是指向的同一个prototype对象,这样提升了运行效率:
c1.callColor == c2.callColor; // true
3.2 prototype的相关属性
一般来说,prototype用于设置和返回构造函数的原型对象,方便实例去继承。
那和它相关的属性还有些什么呢?
还有2个,它们几个纠结于构造函数和实例和原型之间,你们尽可能弄清楚。
__proto__: 设置或返回实例的原型对象
// 1.对象直接量
var p = {}; // 等于new Object()
console.log(p.__proto__ == Object.prototype); // => true
// 2.自定义对象多层继承
function People(name) {
this.name = name;
}
function Student(age) {
this.age = age;
}
Student.prototype = new People(); // 设置Student的原型为People对象
var s = new Student(22);
console.log(s.__proto__); // => People 对象
console.log(Student.prototype); // => People 对象
console.log(s.__proto__ == Student.prototype); // => true
constructor: 表示实例对象的构造函数
// 1.内置对象
var str = 'abc';
console.log(str.constructor); // => function String 构造函数
var o = {};
console.log(o.constructor); // => function Object 构造函数
// 2.自定义对象多层继承 :constructor返回最早调用的构造函数
function People(name) {
this.name = name; // s对象初始化时,先调用People构造函数,再调用Student构造函数
console.log('People调用');
}
function Student(age) {
this.age = age;
console.log('Student调用');
}
Student.prototype = new People(); // 设置Student的原型为People对象
var s = new Student(22);
console.log(s.constructor); // => function People 构造函数
他们的关系能够总结为:
var o = {};
console.log(o.__proto__ === Object.prototype); // true :实例化对象的__proto__等于类的prototype
console.log(o.constructor === Object); // true :实例化对象的constructor等于类
console.log(o.constructor.prototype === Object.prototype); // true :o.constructor.prototype 可表示类的原型。
3.3 prototype的子方法
另外值得说一下的是prototype属性,它还有两个辅助方法,帮助咱们去使用它:
isPrototypeOf():
这个方法用来判断构造函数的原型是不是某个实例的原型:
Ball.prototype.isPrototypeOf(b1);
Ball.prototype.isPrototypeOf(b2);
hasOwnProperty():
这个方法用来判断实例的一个属性是否是本地属性,仍是说是继承自prototype的属性:
b1.hasOwnProperty(“color”);
b1.hasOwnProperty(“jump”);
4.事件event
4.1 事件类型
事件类型就是一个用来讲明发生什么类型事件的字符串
例如mouseover表示用户移动鼠标,keydown表示键盘上某个按键被按下,onload表示文档加载完毕。
在web应用中,处理表单、窗口、鼠标和键盘是最最经常使用的类型了。
表单类型,好比当用户提交表单和重置表单时,form元素就会分别触发submit和reset事件;
当用户改变单选框复选框这些元素的状态时,一般会触发change事件。
窗口类型,则是事件和文档内容无关,会与浏览器窗口自己相关。
好比load事件就是最重要的一个,当文档和外部资源彻底加载并显示出来后就会触发它;
还有当用户调整窗口大小或滚动的时候会触发resize事件和scroll事件。
鼠标类型,就是用户在文档上移动或点击时会触发鼠标事件。
用户移动鼠标时,就会触发mousemove事件,不过这个事件发生很是频繁,千万不要用来计算密集型的任务;
用户按下或释放鼠标按键的时候,会触发mousedown和mouseup事件。
键盘类型,当键盘聚焦到浏览器时,用户每次按下或释放按键时都会产生事件,传递给处理程序的时间对象有keyCode字段,指定了按下或释放的是哪一个键。
4.2 注册事件处理程序
在指明了事件类型后,当特定目标上发生这个类型的事件时,就会调用对应的处理程序,也就是咱们常常所说的触发了事件。
这就须要咱们注册事件的处理程序,一般有这样几种方式:
4.2.1 设置对象属性
这种写法都是由on后面跟着事件名组成:
onclick、onchange、onload等等,而且是全小写:
// 设置window对象的onload属性为一个函数
window.onload = function() {
}
这种方法适合于全部浏览器,但缺点是,一个事件目标的一个事件类型下最多就只能有一个处理程序。
更好的办法后面会讲到。
4.2.2 设置html标签属性
这种写法是写在html标签的属性里,属性值是一个代码字符串:
<button onclick=“alert(‘a string!’);”>click here</button>
浏览器会把代码字符串转换为代码来执行。
但这样作混合js和html,不符合html内容和js行为分离的标准,所以也不是一个好的写法。
4.2.3 addEventListener()
在除了IE9以前的全部浏览器都支持一个方法,addEventListener(),使用这个方法能够为事件目标注册事件处理程序,它能够接收3个参数。
第一个是事件类型,这是个字符串但不包括前缀on;
第二个参数是指定事件发生时应该调用的函数;
最后一个参数是布尔值,一般状况下会传递一个false,但若是传成了true那么函数会注册为捕获事件处理程序。
<button id=“btn”>click me</button>
<script>
var btn = document.getElementById(“btn”);
btn.addEventListener(“click”, function() {
alert(“clicked!”);
}, false);
</script>
4.2.4 attachEvent()
由于IE9之前的IE不支持addEventListener,因此有个相似的方法attachEvent(),其原理和addEventListener差很少,但也有点不一样:
1.由于它不支持事件捕获,所以只有两个参数:事件类型和处理函数。
2.事件类型传递的字符串须要有前缀on
结合这两种方法,常常看到的事件处理程序注册的代码是这样的:
var btn = document.getElementById(“btn”);
var handler = function() {alert(“hello world”);};
if (btn.addEventListener) {
btn.addEventListener(“click”, handler, false);
} else if (btn.attachEvent) {
btn.attachEvent(“onclick”, handler);
}
这样就是在支持addEventListener的浏览器中就调用它,不然就用attachEvent。
4.3 事件的冒泡与捕获
有这么一个思想,咱们都知道一个html页面就是一颗DOM树,那么树上任意一个节点发生的事件是否均可以经过攀爬这课树得知呢?
答案是能够的,这就是事件流。
事件流有冒泡和捕获两种。
4.3.1 冒泡
首先来看一下冒泡:
当click事件在div上发生后,click事件沿着DOM树向上传播,直到document对象上。
这是一种自下而上的顺序,全部的现代浏览器都支持事件冒泡。
4.3.2 捕获
还有一种思路则是捕获,自上而下,其用意在于事件到达目标以前就捕获它:
在捕获过程当中,document对象首先接收到click事件,而后沿着DOM树一路向下,一直传播到事件的实际目标div元素。
但由于老版本浏览器不支持,所以不多有人使用事件捕获,因此建议你们放心使用事件冒泡,特殊须要时再考虑事件捕获。
4.3.3 应用
在了解了基本概念以后,就能够开始考虑实际编码了:
<body>
<div id=“content">
content
<p id=“child">child</p>
</div>
<script>
var content = document.getElementById(“content”);
var child = document.getElementById(“child”);
content.addEventListener(“click”, function() {
alert(“content”);
}, false);
child.addEventListener(“click”, function() {
alert(“child”);
}, false);
</script>
</body>
能够看到这是文档结构很是简单:
body>#content>#child。
分别在content和child上面绑定了一个点击事件,因为addEventListener第三个参数是false,因此是冒泡阶段处理绑定事件。
这个时候点击文本页面有两种行为出现:
1.点击content文本,弹出content。
这个时候就只处罚了content上的点击事件,从content文本节点查找,当前节点没有点击事件;
而后往上找,找到父级#content有绑定事件执行;
再往上找直到document都没有绑定的点击事件,至此冒泡过程结束。
2.点击child文本,先弹出child,再弹出content
理解了上面的代码以后,咱们就能够有事件代理,假设咱们有成千上万个.child标签须要绑定点击事件弹出内容,就无法去挨个绑定了,并且性能也会下降。
这个时候就能够这样作:
var content = document.getElementById("content");
content.addEventListener("click", function(e) {
// 把事件对象当作参数传递过来,但在IE浏览器中,这个e变量是空的,它会在全局的window上,所以这样写了以后就能够两种方式都支持,保证了浏览器的兼容性
var e = e || window.event;
if (e.target.className == "child") {
alert(e.target.innerHTML);
}
}, false);
因为事件冒泡机制的存在,点击了.child以后会冒泡到content上,这个时候就会触发绑定在content上的点击事件,再利用target找到事件实际发生的元素,就能够达到预期效果了
以上就是上节课的内容解析啦
想进一步深刻的同窗欢迎加入咱们的IT交流群828691304共同交流学习!
下节预告
jQuery入门与应用