JavaScript基础学习
一、浏览器发展史
浏览器组成:shell + 内核
内核组成:渲染引擎(语法规则和渲染) + js引擎 + 其他模块
javascript,解释性语言
解释性语言:读一行翻译一行
优点:跨平台
不足:稍慢
编译性语言:通篇翻译
优点:快
不足:移植性不好(不跨平台)
二、变量_值类型_运算符
浏览器
JavaScript
如何引入:
- 标签,内部引用,直接在html里写
- 外部引用
变量
声明变量a,值为100 var a; a = 100;``var a = 100;
命名规则:
- 必须以英文字母,下划线,$开头
- 变量名可以包含英文字母,下划线,$,数字
- 不可以用系统的关键字、保留字作为变量名
值类型
- 原始值
Number Boolean String undefined null
- 引用值
array object function data regexp
运算符
三、比较运算符和逻辑运算符
比较运算符
逻辑运算符
undefined、null、NaN、""、0、false,转化为布尔值都为false,其余都为true
var a = 1 && 2;
👉 返回值为2
先看第一个表达式转换为布尔值的结果,如果结果为真,那么他会看第二个表达式转换为布尔值的结果,然后如果只有两个表达式的话,只要看到第二个表达式就可以返回该表达式的值了。多个表达式类推。
" || " 可用来写兼容
" && " 可用来写中断
四、条件语句和循环语句
条件语句
if(条件){
}
if(1>0){
document.write('hello world');
}
和C差不多
var score = parseInt(window.prompt('input'));
if(score > 90 && score <= 100){
document.write('alibaba');
}else if(score > 80 && score <= 90){
document.write('tencent');
}else if(score > 70 && score <= 80){
document.write('baidu');
}else if(score >= 60 && score <= 70){
document.write('mogujie');
}else if(score >= 0 && score < 60){
document.write('???');
}else{
document.write('error');
}
else if
要求条件必须要互斥
循环语句
for(var i = 0; i < 10; i++){
document.write('a');
}
执行顺序:
- var i = 0;
- if(i < 10){
document.write('a ');
} - i++; --> i = 1
- if(i < 10){
document.write('a ');
} - i++; --> i = 2
…
和C差不多
五、条件语句补充
- switch case
var n = 3;
switch(n) {
case 1:
console.log('a');
break;
case 2:
console.log('b');
break;
case 3:
console.log('c');
break;
case "monday":
console.log('working');
break;
}
- break
break用来终止循环,否则会将后面的语句都执行出来
var i = 0;
while(1) {
i ++;
console.log(i);
if (i > 100) {
break;
}
}
- continue
for (var i = 0; i < 100; i ++) {
if(i % 7 == 0 || i % 10 == 7) {
continue;
}
console.log(i);
}
continue终止本次循环进行下次循环
六、初始引用值
数组
对象
var obj = {
lastName:"kk",
age:44,
sex:undefined
}
console.log(obj.lastName);
deng.lastName = "ll";
console.log(obj.lastName);
七、类型转换
显式类型转换
- Number(mix)
转换为数值
Number(null) --> 0
Number(undefined) --> NaN
- parseInt(string,radix)
把数转换为整型,如果是字符串数则转换成数值,布尔值转换为NaN;如果string位上不仅仅是数字,则从前面一直取到非数字位,打印出来,例如:var demo = "123abc"
,则只打印123
var demo = "10";
var num = paseInt(demo, 16);
console.log(typeof(num) + ":" + num);
radix为基底,意思是把demo的"10",当作16进制的10,转换为10进制的数就是"16",所以这里num的值就为16
- parseFloat(string)
转换为小数,和parseInt相似
- String(mix)
转换为字符串
- Boolean()
转换为布尔类型
- toString(radix)
转换为字符串,null和undefined不能用
var demo = 123;
var num = demo.toString();
console.log(typeof(num) + ":" + num);
进制转换:
// paseInt toString
// 2--------10------16
var num = 10000;
var test = parseInt(num, 2);
console.log(test.toString(16));
隐式类型转换
- isNaN()
先把括号里的 用Number(mix)
转化,再和NaN比较;
是NaN返回true,不是则返回false
- ++/-- +/- (一元正负)
调用Number(mix)
转换为数字类型
转换为字符串
- -*、%
调用Number
- && || !
- < > <= >=
- == !=
undefined == null
- === !==
不发生类型转换,长得不一样就是false,一模一样才为true
八、函数
function 函数名(){
}
function sum(a,b) {
a = 2;
arguments[0] = 3;
console.log(a);
}
sum(1,2);
return可以终止函数,也可以返回值
逆转数字:
function reverse() {
var num = window.prompt('input');
for (var i = num.length - 1; i >= 0; i -- ){
str += transfer(num[i]); //拿出当前位
}
document.write(str);
}
function transfer(target) {
switch(target) {
case "1" :
return "一";
case "2" :
return "二";
case "3" :
return "三";
case "4" :
return "四";
case "5" :
return "五";
case "6" :
return "六";
case "7" :
return "七";
case "8" :
return "八";
case "9" :
return "九";
}
}
n的阶乘
function jc(n) {
if (n == 1) {
return 1;
}
return n * jc(n - 1)
}
九、递归
- 找规律
- 找出口(结束条件)
斐波那契数列:
function fb(n) {
if(n == 1 || n == 2) {
return 1;
}
return fb(n - 1) + fb(n - 2);
}
十、预编译
window就是全局的域
预编译过程:
AO对象,activation object,执行期上下文
例一:
function fn(a) {
console.log(a); //function a() {}
var a = 123;
console.log(a); //123
function a () {}
console.log(a); //123
var b = function () {}
console.log(b); //function () {}
function d() {}
}
fn(1);
具体过程参考:https://www.bilibili.com/video/BV1f4411R7M5?p=12 1:00:00
例二
a = 100;
function demo(e) {
function e() {}
arguments[0] = 2;
console.log(e); //2
if(a) {
var b = 123;
function c() {}
}
var c;
a = 10;
var a;
console.log(b); //undefined
f = 123;
console.log(c); //function () {}
console.log(a); //10
}
var a;
demo(1);
console.log(a); //100
console.log(f): //123
例三
var str = false + 1;
document.write(str); //1
var demo = false == 1;
document.write(demo); //false
if(typeof(a) && -true + (+undefined) + ""){
document.write('abcde'); //能打印
}
if(11 + "11" * 2 == 33){
document.write('abcd'); //能打印
}
!!" " + !!"" - !!false||document.write('qzwsx'); //不能打印
十一、作用域
function a() {
function b() {
var b = 234;
}
var a = 123;
b();
}
var glob = 100;
a();
十二、立即执行函数
定义:此类函数没有声明,在一次执行过后即释放。适合做初始化工作。
(function abc(){
var a = 123;
var b = 234;
console.log(a + b);
}())
👆执行完后函数就找不到了:
只有表达式才能被执行符号执行,被执行符号执行后的函数表达式,被永久放弃掉,相当于成了立即执行函数
例1:
var test = function () {
console.log('a');
}();
👆这里test函数就没了
例2:
+ function test1 () {
console.log('a');
}();
- function test2 () {
console.log('b');
}();
! function test3 () {
console.log('c');
}();
同上,"+"、"!“和”-“都将其变成表达式,参考前面的笔记,”*“和”%"不行
十三、闭包**
当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏。
1、闭包的作用
- 实现公有变量
eg:函数累加器
function add() {
var count = 0;
function demo() {
count ++;
console.log(count);
}
return demo;
}
var counter = add();
counter();
counter();
counter();
counter();
counter();
counter();
- 可以做缓存(存储结构)
eg:eater
function test() {
var num = 100;
function a () {
num ++;
console.log(num);
}
function b () {
num --;
console.log(num);
}
return [a,b];
}
var myArr = test();
myArr[0]();
myArr[1]();
👆这里a和b的testAO是同一个
function eater() {
var food = "";
var obj = {
eat : function() {
console.log("i am eating " + food);
food = "";
},
push : function (myFood) {
food = myFood;
}
}
return obj;
}
var eater1 = eater();
eater1.push('banana');
eater1.eat();
- 可以实现封装,属性私有化
eg:Person(); - 模块化开发,防止污染全局变量
2、利用立即执行函数解决闭包 **
使用立即执行函数前:
function test() {
var arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = function() {
document.write(i);
}
}
return arr;
}
var myArr = test();
for (var j = 0; j < 10; j++) {
myArr[j]();
}
👆此处打印10个“10”
使用立即执行函数后:
function test() {
var arr = [];
for (var i = 0; i < 10; i++) {
(function (j) {
arr[j] = function () {
console.log(j);
}
}(i))
}
return arr;
}
var myArr = test();
for (var j = 0; j < 10; j++) {
myArr[j]();
}
👆此处打印“0”~“9”
十四、对象
定义
var MrDu = {
name : "Qingsong Du",
age : 23,
sex : "male",
health : 100,
smoke : function () {
console.log('I am smoking ! cool !!!');
this.health --;
},
drink : function () {
console.log('I am drinking!');
this.health ++;
}
}
增删改查
删:
delete MrDu.name
对象的创建方法
1. var obj = {}
plainObject 对象字面量/对象直接量
2. 构造函数
①系统自带的构造函数 new Object()
var obj = new Object();
obj.name = 'abc';
obj.sex = 'male';
obj.say = function (){}
②自定义
function Car(color) {
this.color = color;
this.name = 'BMW';
this.height = '1400';
this.lang = '4900';
this.weight = 1000;
this.health = 100;
this.run = function () {
this.health --;
}
}
var car = new Car('red');
var car1 = new Car('green');
car.name = 'Maserati';
car1.name = 'Merz';
function Student(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.grade = 2017;
}
var student = new Student('zhangsan', 18, 'male');
③构造函数内部原理
- 在函数体最前面隐式的加上this = {}
- 执行
this.xxx = xxx
- 隐式地返回this
十五、 包装类
例一:
var str = "abc";
str += 1;
var test = typeof(str);
if(test.length == 6) {
test.sign = "typeof的返回结果可能为String";
//new String(test).sign = 'xxx';
//delete
}
//new String (test).sign 跟上面那个不一样,啥都没有了
console.log(test.sign);
结果:打印
undefined
例二:
function Person(name, age, sex) {
var a = 0;
this.name = name;
this.age = age;
this.sex = sex;
function sss() {
a ++;
document.write(a);
}
this.say = sss;
}
var oPerson = new Person();
oPerson.say(); //1
oPerson.say(); //2
var oPerson1 = new Person();
oPerson1.say(); //1
十六、原型
定义
原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。描述一种继承的关系。
利用原型特点和概念,可以提取共有属性
对象如何查看原型
隐式属性 __proto__
例一:
Person.prototype.name = 'abc';
function Person() {
//var this = {
//
//__proto__ : Person.prototype
//}
}
var obj = {
name : "sunny"
}
var person = new Person();
person.__prototype__ = obj;
👆打印
person.name
,输出"sunny"
例二:
Person.prototype.name = 'sunny';
function Person() {
//var this = {__proto__ : Person.prototype}
}
var person = new Person();
Person.prototype = {
name : 'cherry'
}
//理解:
//Person.prototype = {name : "a"};
//__proto__ = Person.prototype;
//Person.prototype = {name : "b"};
👆打印
person.name
,输出"sunny"
例三:
Person.prototype.name = 'sunny';
function Person() {
//var this = {__proto__ : Person.prototype}
}
Person.prototype = {
name : 'cherry'
}
var person = new Person();
👆打印
person.name
,输出"cherry"
;
ps:var person = new Person()
执行过后,才会有//var this = {__proto__ : Person.prototype}
,所以此处先将前面的'sunny'
覆盖了
对象如何查看对象的构造函数
constructor
十七、原型链
定义
Grand.prototype.lastName = "Deng";
function Grand() {
}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'xuming';
}
var father = new Father();
Son.prototype = father;
function Son() {
this.hobbit = 'smoke';
}
var son = new Son();
增删改查
绝大多数对象的最终都会继承自Object.prototype
toString
123.toString()
👈不能这样调用,这样会把 “.” 和数字连到一起,识别成浮点型
十八、call/apply
作用
改变this指向
function Person(name, age) {
this.name = name;
this.age = age
}
var person = new Person('deng', 100);
var obj = {}
Person.call(obj, 'cheng', 300); //Person里的this全部换成obj
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade) {
//var this = {name:"", age:"", sex:""}
Person.call(this, name, age, sex);
this.tel = tel;
this.grade = grade;
}
var student = new Student('sunny', 123, 'male', 139, 2017);
区别
传参列表不同
call需要把实参按形参的个数传进去,apply需要传一个实参列表(数组)
例:wheel.apply(this, [wheelSize, style]);
wheel.call(this, wheelSize, style);
十九、继承模式
继承发展史
- 传统形式👉原型链
- 过多继承了没用的属性
- 借用构造函数
- 不能继承借用构造函数的原型
- 每次构造函数都要多走一个函数
- 共享原型
- 不能随便改动自己的原型
Father.prototype.lastName = "Deng";
function Father() {
}
function Son() {
}
function inherit(Target, Origin) {
Target.prototype = Origin.prototype;
}
inherit(Son, Father);
var son = new Son();
- 圣杯模式
function inherit(Target, Origin) {
function F() {};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
Father.prototype.lastName = "Deng";
function Father() {
}
function Son() {
}
inherit(Son, Father);
var son = new Son();
var father = new Father();
命名空间
管理变量,防止污染全局,适用于模块化开发
var name = 'bcd';
var init = (function (){
var name = 'abc';
function callName() {
console.log(name);
}
return function () {
callName();
}
}())
var initDeng = (function (){
var name=123;
function callName() {
console.log(name);
}
return function () {
callNae();
}
}())
互相不污染👆,同闭包的第四个作用
连续调用
var deng = {
smoke : function () {
console.log('donda');
return this;
},
drink : function () {
console.log('donda1');
return this;
},
perm : function () {
console.log('donda2');
return this;
},
}
deng.smoke().drink().perm().smoke().drink();
属性调用的其他方法
deng.sayWife
== deng['sayWife']
例:
var deng = {
wife1 : {name : "xiaoliu"},
wife2 : {name : "xiaozhang"},
wife3 : {name : "xiaomeng"},
wife4 : {name : "xiaowang"},
sayWife : function (num) {
return this['wife' + num];
}
}
对象的枚举
var obj = {
name : 123,
age : 234,
sex : "male",
height : 524
}
for (var prop in obj) {
//console.log(obj.prop --> obj['prop']);
console.log(obj[prop]);
}
obj.hasOwnProperty(属性名)
判断是否为自己的属性,返回布尔值
instanceof
A instanceof B
看A对象是不是构造函数B构造出来的
或 看A对象的原型链上,有没有B的原型
二十、深度克隆
- 遍历对象
for(var prop in obj)
- 判断是原始值还是引用值
typeof()
- 如果是引用值,判断是数组还是对象
instanceof toString constructor
- 建立相应的数组或对象
- 递归
function deepClone(origin, target) {
var target = target || {},
toStr = Object.prototype.toString,
arrStr = "[object Array]";
for (var prop in origin) {
if (origin.hasOwnProperty(prop)) {
if (origin[prop] !== "null" && typeof(origin[prop]) == 'object') {
// if(toStr.call(origin[prop]) == arrStr) {
// target[prop] = [];
// }else{
// target[prop] = {};
// }
target[prop] = (toStr.call(origin[prop]) == arrStr) ? [] : {};
deepClone(origin[prop], target[prop]);
}else{
target[prop] = origin[prop];
}
}
}
return target;
}
二十一、数组
数组的定义
arr = new Array(length/content)
var arr = []
数组的常用方法
改变原数组的一类
- arr.push()
在数组的最后一位开始添加数据,可添加多位
- arr.pop()
把数组的最后一位剪切出去
- arr.shift()
从数组前面剪一位
- arr.unshift()
在数组前面添加数据,可添加多位
- arr.splice
arr.splice(从第几位开始, 截取的长度, 在切口处添加新的数据)
- arr.reverse
数组顺序反过来
- arr.sort
给数组排序,按字符串排。但是可以自行定义规则:
//1. 必须写俩形参
//2. 看返回值 1) 当返回值为负数时,前面的数放在前面
// 2) 当返回值为正数时,后面的数放在前面
// 3) 当返回值为0时,不动
var arr = [1, 3, 5, 4, 10];
arr.sort(function (a, b) {
//return a-b; 按数字大小升序
//return b-a; 按数字大小降序
})
//传参规则参照**冒泡排序** ,即第一位先跟后面所有比较,再第二位,再第三位.....
// 将一个有序的数组乱序,一次性返回
var arr = [1, 2, 3, 4, 5, 6, 7]
arr.sort(function() {
return Math.random() - 0.5;
})
var cheng = {
name : "cheng",
age : 18,
sex : 'male',
face : "handsome"
}
var deng = {
name : "deng",
age : 40,
sex : undefined,
face : "amazing"
}
var zhang = {
name : "zhang",
age : 20,
sex : "male"
}
var arr = [cheng, deng, zhang];
arr.sort(function(a, b) {
return a.age - b.age; //按年龄大小排
})
//按字节大小排序
function retBytes(str) {
var num = str.length;
for (var i = 0; i < str.length; i++) {
if(str.charCodeAt(i) > 255) {
num ++;
}
}
return num;
}
var arr = ['a登','iub低','aosij顶阿斯蒂和','阿斗阿瑟东吧','hih霓虹灯'];
arr.sort(function (a, b) {
return retBytes(a) - retBytes(b);
})
不改变原数组的一类
- arr.concat(arr1)
将arr1拼到arr后面,生成一个新的数组,可用变量接收,不改变原arr和arr1数组
- arr.toString()
把数组变成字符串,返回,不改变原数组
- arr.slice(从该位开始截取,截取到该位但不包含该位)
不改变原数组,不写参数就是截取整个数组
- arr.join(参数)
将数组中的每个元素用传入的参数连接起来,并转换成字符串,不改变原数组
- str.split(参数)
与join互逆,将字符串按传入的参数拆分成数组,例:
//将下列字符串连到一起
var str = "alibaba";
var str1 = "baidu";
var str2 = "tencent";
var str3 = "toutiao";
var str4 = "wangyi";
var str5 = "xiaowang";
var str6 = "abcd";
var arr = [str, str1, str2, str3, str4, str5, str6];
var strFinal = arr.join(" ");
二十二、类数组
var obj = {
"0" : 'a',
"1" : 'b',
"2" : 'c',
"length" : 3,
"push" : Array.prototype.push
}
属性要为索引(数字)属性,必须有length属性,最好加上push
push的内部原理如下:
Array.prototype.push = function (target) {
obj[obj.length] = target;
obj.length ++;
}
阿里巴巴题目:
var obj = {
"2" : "a",
"3" : "b",
"length" : 2,
"push" : Array.prototype.push
}
obj.push('c');
obj.push('d');
结果:
既具有对象的特性又有数组的特性,好用得很
二十三、try…catch
try{
}catch(e) {
}
不知道try里面的代码有没有错误。若try中有错误,则不会执行错误后的try里面的代码,仍然执行try{}catch{}之后的代码
error.name的六种值对应的信息(错误类型):
- EvalError:eval()的使用与定义不一致
- RangeError:数值越界
- ReferenceError:非法或不能识别的引用数值
没定义就用
- SyntaxError:发生语法解析错误
语法有问题
- TypeError:操作数类型错误
- URIError:URI处理函数使用不当
二十四、es5严格模式
use strict
不再兼容es3的一些不规则语法。使用全新的es5规范。
两种用法:
- 全局严格模式
- 局部函数内严格模式(推荐)
就是一行字符串,不会对不兼容严格模式的浏览器产生影响
二十五、dom
什么是dom
dom ——> document object model
dom定义了表示和修改文档所需的方法。dom对象即为宿主对象,由浏览器厂商定义,用来操作html和xml功能的一类对象的集合。也有人称dom是对html以及xml的标准变成接口。
//dom对象
var div = document.getElementsByTagName('div')[0]; // 选择第一个div标签
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "red";
div.onclick = function () {
this.style.backgroundColor = "green";
this.style.width = "200px";
this.style.height = "50px";
this.style.borderRadius = "50%";
}
<!-- 选项卡 -->
<head>
<style type = "text/css">
.content{
display:none;
width:200px;
height:200px;
border:2px solid red;
}
.active {
background-color:yellow;
}
</style>
</head>
<body>
<div class = "wrapper">
<button class = "active">123</button>
<button>234</button>
<button>345</button>
<div class = "content" style = "display:block">aaa</div>
<div class = "content">bbb</div>
<div class = "content">ccc</div>
</div>
<script type = "text/javascript">
var btn = document.getElementsByTagName('button');
var div = document.getElementsByClassName('content');
for (var i = 0; i < btn.length; i++) {
(function (n){
btn[n].onclick = function () {
for (var j = 0; j < btn.length; j++) {
btn[j].className = "";
div[j].style.display = "none";
}
this.className = "active";
div[n].style.display = "block";
}
}(i))
}
</script>
</body>
var div = document.createElement('div');
document.body.appendChild(div);
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "red";
div.style.position = "absolute";
div.style.left = "0";
div.style.top = "0";
setInterval(function () {
div.style.left = parseInt(div.style.left) + 1 + "px";
}, 100); //每隔100毫秒就执行一次function函数
// 移动方块
// <button style="width:100px; height:50px; background:linear-gradient(to left, #999, #000, #432, #fcc); position:fixed; right:0; top:50%; text-align:center; line-height:50px; color:#fff; font-size:25px; font-family:arial;">加速</button>
var btn = document.getElementsByTagName('button')[0];
var div = document.createElement('div');
document.body.appendChild(div);
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundColor = "red";
div.style.position = "absolute";
div.style.left = "0";
div.style.top = "0";
var speed = 5;
btn.onclick = function () {
speed ++;
}
document.onkeydown = function(e) {
switch(e.which) {
case 38:
div.style.top = parseInt(div.style.top) - speed +"px";
break;
case 40:
div.style.top = parseInt(div.style.top) + speed +"px";
break;
case 37:
div.style.left = parseInt(div.style.left) - speed +"px";
break;
case 39:
div.style.left = parseInt(div.style.left) + speed +"px";
break;
}
}
<!-- 刮刮乐 -->
<style>
*{
margin:0;
padding:0;
}
li{
box-sizing: border-box;
float:left;
width:10px;
height:10px;
border:1px solid black;
}
ul{
list-style: none;
width:200px;
height:200px;
}
</style>
</head>
<body>
<ul>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
<li img-date="0"></li>
</ul>
<script type="text/javascript">
var ul = document.getElementsByTagName('ul')[0];
ul.onmouseover = function (e) {
var event = e || window.event;
var target = event.target || event.srcElement;
target.style.backgroundColor = "rgb(0, 255," + target.getAttribute('img-date') + ")";
target.setAttribute('img-date', parseInt(target.getAttribute('img-date')) + 20);
}
</script>
方法
查看元素节点
document //代表整个文档
document.getElementById() //元素id在IE8以下的浏览器,不分大小写,而且也返回匹配name属性的元素
document.getElementsByTagName() //标签名
document.getElementsByName() //只有部分标签name可生效(表单、表单元素、img、iframe)
document.getElementsByClassName() //类名 -> ie8和ie8以下的ie版本中没有
document.querySelector() //css选择器 在ie7和ie7以下的版本中没有
document.querySelectorAll() //css选择器 在ie7和ie7以下的版本中没有
遍历节点树(包括文本节点)
parentNode //父节点 (最顶端的parentNode为#document)
childNodes //子节点们
firstChild //第一个子节点
lastChild //最后一个子节点
nextSibling //后一个兄弟节点
previousSibling //前一个兄弟节点
基于元素节点树的遍历
parentElement //返回当前元素的父元素节点(IE不兼容)
children //只返回当前元素的元素子节点
node.childElementCount === node.children.length //当前元素节点的子元素个数
firstElementChild //返回的是第一个元素节点
lastElementChild //返回的是最后一个元素节点
nextElementSibling/previousElementSibling //返回后一个/前一个兄弟元素
节点的四个属性
- nodeName
元素的标签名,以大写形式表示,只读
- nodeValue
Text节点或Comment节点的文本内容,可读写
- nodeType
该节点的类型,只读
- attributes
Element节点的属性集合
<div>
<!-- This is comment! -->
<strong></strong>
<span></span>
<em></em>
<i></i>
<b></b>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
function retElementChild(node) {
var temp = {
length : 0,
push : Array.prototype.push,
splice : Array.prototype.splice
},
child = node.childNodes,
len = child.length;
for (var i = 0; i < len; i++){
if (child[i].nodeType === 1) {
temp.push(child[i]);
}
}
return temp;
}
console.log(retElementChild(div));
</script>
dom结构树
练习:
- 封装函数,返回元素e的第n层祖先元素节点
<div>
<strong>
<span>
<i></i>
</span>
</strong>
</div>
<script type = "text/javascript">
function retParent(elem, n) {
while(elem && n) {
elem = elem.parentElement;
n --;
}
return elem;
}
</script>
- 编辑函数,封装myChildren功能,解决以前部分浏览器的兼容性问题
<div>
<b></b>
abc
<!-- this is comment! -->
<strong>
<span>
<i></i>
</span>
</strong>
</div>
<script type = "text/javascript">
Element.prototype.myChildren = function () {
var child = this.childNodes;
var len = child.length;
var arr = [];
for (var i = 0; i < len; i ++) {
if (child[i].nodeType == 1) {
arr.push(child[i]);
}
}
return arr;
}
var div = document.getElementsByTagName('div')[0];
</script>
- 自己封装hasChildren()方法,不可用children属性
<div>
<b></b>
abc
<!-- this is comment! -->
<strong>
<span>
<i></i>
</span>
</strong>
</div>
<script type = "text/javascript">
Element.prototype.myChildren = function () {
var child = this.childNodes;
var len = child.length;
var arr = [];
for (var i = 0; i < len; i ++) {
if (child[i].nodeType == 1) {
return true;
}
}
return false;
}
var div = document.getElementsByTagName('div')[0];
</script>
- 封装函数,返回元素e的第n个兄弟元素节点,n为正,返回后面的兄弟元素节点,n为负,返回前面的,n为0,返回自己
<div>
<span></span>
<p></p>
<strong></strong>
<i></i>
<address></address>
</div>
<script type = "text/javascript">
function retSibling(e, n) {
while(e && n) {
if(n > 0) {
e = e.nextElementSibling;
n --;
}else {
e = e.previousElementSibling;
n ++;
}
}
return e;
}
var strong = document.getElementsByTagName('strong')[0];
</script>
dom基本操作
增:
document.createElement();
document.createTextNode();
document.createComment();
document.createDocumentFragment();
插:
PARENTNODE.appendChild();
PARENTNODE.insertBefore(a,b);
删:
parentNode.removeChild(); //剪切出来
childNode.remove();
替换:
parentNode.replaceChild(new, origin);
Element节点的一些属性和方法
属性
innerHTML
innerText//火狐不兼容
textContent// 老版本IE不好使
方法
ele.setAttribute()
ele.getAttribute()
<div></div>
<span></span>
<strong></strong>
<script type="text/javascript">
var all = document.getElementsByTagName('*');
for (var i = 0; i < all.length; i++) {
all[i].setAttribute('this-name', all[i].nodeName);
}
</script>
二十六、日期对象Date()
封装函数,打印当前是何年何月何日何时,几分几秒
//一千万圈用的时间
var firstTime = new Date().getTime();
for (var i = 0; i < 10000000; i++){}
var lastTime = new Date().getTime();
console.log(lastTime - firstTime);
var firstTime = new Date().getTime();
setInterval(function () {
var lastTime = new Date().getTime();
console.log(lastTime - firstTime);
firstTime = lastTime;
}, 1000);
二十七、获取窗口属性,获取dom尺寸
查看滚动条的滚动距离
window.pageXOffset/pageYOffset //IE8及IE8以下不兼容
document.body/documentElement.scrollLeft/scrollTop //兼容性比较混乱,用时取两个值相加,因为不可能存在两个同时有值
封装一个getScrollOffset()
函数,兼容性方法,求滚动轮滚动距离
function getScrollOffset() {
if(window.pageXOffset) { //判断条件:当window.pageXOffset是否好用的时候(兼容性)
return {
x : window.pageXOffset,
y : window.pageYOffset
}
}else {
return {
x : document.body.scrollLeft + document.documentElement.scrollLeft,
y : document.body.scrollTop + document.documentElement.scrollTop
}
}
}
查看视口的尺寸
window.innerWidth/innerHeight //IE8及IE8以下不兼容
document.documentElement.clientWidth/clientHeight //标准模式下,任意浏览器都兼容
document.body.clientWidth/clientHeight //适用于怪异模式下的浏览器
封装一个getViewportOffset()
函数,兼容性方法,返回浏览器视口尺寸
function getViewportOffset() {
if (window.innerWidth) {
return {
w : window.innerWidth,
h : window.innerHeight
}
}else {
if (document.compatMode === "BackCompat") {
return {
w : document.body.clientWidth,
h : document.body.clientHeight
}
}else {
return {
w : document.documentElement.clientWidth,
h : document.documentElement.clientHeight
}
}
}
}
查看元素的几何尺寸
domEle.getBoundingClientRect();
//兼容性很好
//该方法返回一个对象,对象里有left,top,right,bottom等属性。left和top代表该元素左上角的X和Y坐标,right和bottom代表元素右下角的X和Y的坐标
//height和width老版本IE并未实现
//返回的结果不是实时的
查看元素的尺寸
dom.offsetWidth;
dom.offsetHeight;
查看元素的位置
dom.offsetLeft
dom.offsetTop
//对于无定位父级的元素,返回相对文档的坐标。对于有定位父级的元素,返回相当于最近的有定位的父级的坐标
dom.offsetParent
//返回最近的有定位的父级,若无,返回body,body.offsetParent
让滚动条滚动
//window上有三个方法
scroll();
scrollTo();
scrollBy();
//三个方法功能类似,用法都是将x,y坐标传入。即实现让滚动轮滚动到当前位置。
//区别:scrollBy()会在之前的数据基础上做累加
实现自动阅读功能:
<head>
<p>这里有非常多的文字</p>
<div style="width: 100px;height: 100px;background-color:orange;color:blue;font-size: 40px;font-weight: bold;text-align: center;line-height: 100px;position: fixed;bottom:250px;right: 50px;border-radius: 50%;opacity: 0.5;">
Start
</div>
<div style="width: 100px;height: 100px;background-color:orange;color:blue;font-size: 40px;font-weight: bold;text-align: center;line-height: 100px;position: fixed;bottom:100px;right: 50px;border-radius: 50%;opacity: 0.5;">
Stop
</div>
</head>
<body>
<script type="text/javascript">
var start = document.getElementsByTagName('div')[0];
var stop = document.getElementsByTagName('div')[1];
var timer = 0;
var lock = true; //加锁
start.onclick = function () {
if (lock) {
timer = setInterval(function () {
window.scrollBy(0, 10);
}, 100);
lock = false;
}
}
stop.onclick = function () {
clearInterval(timer);
lock = true;
}
</script>
</body>
二十八、脚本化CSS
读写元素css属性
dom.style.prop
//可读写 **行间** 样式,没有兼容性问题,碰到float这样的保留字属性,前面应加css
//复合属性必须拆解,组合单词变成小驼峰式写法
//写入的值必须是字符串格式
查询计算样式
window.getComputedStyle(ele, null);
//计算样式只读
//返回的计算样式的值都是绝对值,没有相对单位
//IE8及IE8以下不兼容
查询样式
ele.currentStyle
//计算样式只读
//返回的计算样式的值不是经过转换的绝对值
//IE独有的属性
封装一个getStyle(elem, prop)
函数,兼容性方法
function getStyle(elem, prop) {
if (window.getComputedStyle) {
return window.getComputedStyle(elem, null)[prop];
}else {
return elem.currentStyle[prop];
}
}
让小方块移动:
<head>
<div style="width: 100px;height: 100px;background-color: cadetblue;position: absolute;left: 0;top: 0;"></div>
</head>
<body>
<script type="text/javascript">
function getStyle(elem, prop) {
if (window.getComputedStyle) {
return window.getComputedStyle(elem, null)[prop];
}else {
return elem.currentStyle[prop];
}
}
var div = document.getElementsByTagName('div')[0];
var timer = setInterval(function () {
div.style.left = parseInt(getStyle(div, 'left')) + 10 + 'px';
if (parseInt(div.style.left) > 500) {
clearInterval(timer);
}
}, 100);
</script>
</body>
二十九、事件
如何绑定事件处理函数
//type - 事件类型
//fn - 处理函数
ele.onxxx = function (event) {}
//兼容性很好,但是一个元素的同一个事件上只能绑定一个处理程序
//基本等同于写在HTML行间上
obj.addEventListener(type, fn, false)
//IE9以下不兼容,可以为一个事件绑定多个处理程序
obj.attachEvent('on'+type, fn)
//IE独有,一个事件同样可以绑定多个处理程序
点击四个a按顺序打印数字:
<body>
<ul>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
</ul>
<script type="text/javascript">
var liCol = document.getElementsByTagName('li');
var len = liCol.length;
for(var i = 0; i < len; i++) {
(function(i) {
liCol[i].addEventListener('click', function () {
console.log(i);
}, false)
} (i))
}
</script>
</body>
<!-- 用立即执行函数解决闭包问题,每当有绑定事件处理函数出现在循环里时,就要考虑是否会出现闭包 -->
事件处理程序的运行环境
ele.onxxx = function (event) {}
//程序this指向是dom元素本身
obj.addEventListener(type, fn, false)
//程序this指向是dom元素本身
obj.attachEvent('on'+type, fn)
//程序this指向window
封装兼容性的addEvent(elem, type, handle)方法:
function addEvent(elem, type, handle) {
if(elem.addEventListener) {
elem.addEventListener(type, handle, false);
}else if(elem.attachEvent) {
elem.attachEvent('on'+type, function() {})
}else{
elem['on'+type] = handle;
}
}
解除事件处理程序
ele.onclick = false/''/null
ele.removeEventListener(type, fn, false)
ele.detachEvent('on'+type, fn)
//注:若绑定匿名函数,则无法解除
var div = document.getElementsByTagName('div')[0];
div.onclick = function () {
console.log('a');
this.onclick = null;
}
var div = document.getElementsByTagName('div')[0];
div.addEventListener('click',test,false);
function test() {
console.log('a');
}
div.removeEventListener('click',test,false);
事件处理模型 - 事件冒泡、捕获
<head>
<style type="text/css">
.wrapper{
width:300px;
height:300px;
background-color:red;
}
.content{
width:200px;
height:200px;
background-color:green;
}
.box{
width:100px;
height:100px;
background-color:yellow;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="content">
<div class="box"></div>
</div>
</div>
<script type="text/javascript">
var wrapper = document.getElementsByClassName('wrapper')[0];
var content = document.getElementsByClassName('content')[0];
var box = document.getElementsByClassName('box')[0];
wrapper.addEventListener('click', function() {
console.log('wrapper')
}, false);
content.addEventListener('click', function() {
console.log('content')
}, false);
box.addEventListener('click', function() {
console.log('box')
}, false);
</script>
</body>
事件冒泡
结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底至上)
事件捕获
结构上(非视觉上)嵌套关系的元素,会存在事件捕获功能,即同一事件,自父元素捕获至子元素(事件源事件)。(自顶向下),打印的刚好和事件冒泡顺序相反。
执行方法:把false改成true。
IE没有捕获事件。
触发顺序:先捕获,后冒泡
focus,blur,change,submit,reset,select等事件不冒泡
取消冒泡和阻止默认事件
取消冒泡
W3C标准
event.stopPropagation();
但不支持ie9以下版本
IE独有event.cancelBubble = true;
封装取消冒泡的函数 stopBubble(event):
function stopBubble(event) {
if(event.stopPropagation) {
event.stopPropagation();
}else {
event.cancelBubble = true;
}
}
阻止默认事件
默认事件 - 表单提交,a标签跳转,右键菜单等
1. return false;//以对象属性的方式注册的事件才能生效
2. event.preventDefault();//W3C标注,IE9以下不兼容
3. event.returnValue = false; //兼容IE
封装阻止默认事件的函数cancelHandler(event):
function cancelHandler(event) {
if(event.preventDefault) {
event.preventDefault(;)
}else {
event.returnValue = false;
}
}
事件对象
event || window.event // 用于IE
//事件源对象:
event.target //火狐只有这个
event.srcElement //IE只有这个
//这两个chrome都有
事件委托
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
<script type="text/javascript">
var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function(e) {
var event = e || window.event;
var target = event.target || event.srcElement;
console.log(target.innerText);
}
</script>
利用事件冒泡,和事件源对象进行处理
优点:
- 性能 不需要循环所有的元素一个个绑定事件
- 灵活 当有新的子元素时不需要重新绑定事件
事件分类
拖拽事件
<div style="width:100px;height:100px;background-color:red;position:absolute;left:0;top:0;"></div>
<script type="text/javascript">
var div = document.getElementsByTagName('div')[0];
var disX,
disY;
div.onmousedown = function (e) {
disX = e.pageX - parseInt(div.style.left);
disY = e.pageY - parseInt(div.style.top);
document.onmousemove = function (e) {
var event = e || window.event;
div.style.left = e.pageX - disX + "px";
div.style.top = e.pageY - disY + "px";
}
document.onmouseup = function () {
div.onmousemove = null;
}
}
</script>
鼠标事件
click、mousedown、mousemove、mouseup、contextmenu、mouseover、mouseout、mouseenter、mouseleave
//用button来区分鼠标的按键,0/1/2
//dom3标准规定:click事件只能监听左键,只能通过mousedown和mouseup来判断鼠标键
键盘事件
keydown keyup keypress
keydown > keypress > keyup
// keydown和keypress的区别:
// keydown可以响应任何键盘按键,keypress只可以响应字符类键盘按键
// keypress返回ASCII码,可以转换成相应字符
文本操作事件
input、focus、blur、change
三十、JSON
JSON是一种传输数据的格式(以对象为样板,本质上就是对象,但用途有区别,对象就是本地用的,JSON是用来传输的)
JSON.stringify() // json(对象) -> string
JSON.parse() // string -> json(对象)
异步加载js
js加载的缺点:加载工具方法没必要阻塞文档,过多js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作。
有些工具方法需要按需加载,用到的时候加载,不用的时候就不加载。
JavaScript异步加载的三种方案
- defer异步加载,你加载你的我加载我的,一起加载,但要等到dom文档全部解析完才会被执行。只有IE能用,也可以将代码写到内部。例:
<script type="text/javascript" src="tools.js" defer="defer"></script>
- async异步加载,加载完就执行,async只能加载外部脚本,不能把js写在script标签里。例:
<script type="text/javascript" src="tools.js" async="async"></script>
- 创建script,插入到dom中,加载完毕后callBack
function loadScript(url, callback) {
var script = document.createElement('script');
script.type = "text/javascript";
if(script.readyState) {
script.onreadystatechange = function () {
if(script.readyState == "complete" || script.readyState == "loaded") {
callback();
}
}
}else{
script.onload = function () {
callback();
}
}
script.src = url;
document.head.appendChild(script);
}
loadScript('demo.js', function () {
test();
});