JavaScript基础学习

JavaScript基础学习

一、浏览器发展史

浏览器组成:shell + 内核
内核组成:渲染引擎(语法规则和渲染) + js引擎 + 其他模块

javascript,解释性语言

解释性语言:读一行翻译一行
优点:跨平台
不足:稍慢

编译性语言:通篇翻译
优点:快
不足:移植性不好(不跨平台)

二、变量_值类型_运算符

浏览器

在这里插入图片描述

JavaScript

如何引入:

  1. 标签,内部引用,直接在html里写
  2. 外部引用

    在这里插入图片描述

变量

声明变量a,值为100 var a; a = 100;``var a = 100;

命名规则:

  1. 必须以英文字母,下划线,$开头
  2. 变量名可以包含英文字母,下划线,$,数字
  3. 不可以用系统的关键字、保留字作为变量名

值类型

  1. 原始值

Number Boolean String undefined null

  1. 引用值

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');
}

执行顺序:

  1. var i = 0;
  2. if(i < 10){
    document.write('a ');
    }
  3. i++; --> i = 1
  4. if(i < 10){
    document.write('a ');
    }
  5. i++; --> i = 2

和C差不多

五、条件语句补充

  1. 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;

        }
  1. break

break用来终止循环,否则会将后面的语句都执行出来

var i = 0;
while(1) {
    i ++;
    console.log(i);
    if (i > 100) {
        break;
    }
}
  1. 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);

七、类型转换

显式类型转换

  1. Number(mix)

转换为数值

Number(null) --> 0
Number(undefined) --> NaN
  1. 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

  1. parseFloat(string)

转换为小数,和parseInt相似

  1. String(mix)

转换为字符串

  1. Boolean()

转换为布尔类型

  1. 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));

隐式类型转换

  1. isNaN()

先把括号里的 用Number(mix)转化,再和NaN比较;
是NaN返回true,不是则返回false

  1. ++/-- +/- (一元正负)

调用Number(mix)转换为数字类型

转换为字符串

  1. -*、%

调用Number

  1. && || !
  2. < > <= >=
  3. == !=

在这里插入图片描述

undefined == null
  1. === !==

不发生类型转换,长得不一样就是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)
}

九、递归

  1. 找规律
  2. 找出口(结束条件)

斐波那契数列:

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');

③构造函数内部原理

  1. 在函数体最前面隐式的加上this = {}
  2. 执行this.xxx = xxx
  3. 隐式地返回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);

十九、继承模式

继承发展史

  1. 传统形式👉原型链
  • 过多继承了没用的属性
  1. 借用构造函数
  • 不能继承借用构造函数的原型
  • 每次构造函数都要多走一个函数
  1. 共享原型
  • 不能随便改动自己的原型
Father.prototype.lastName = "Deng";
function Father() {

}

function Son() {

}

function inherit(Target, Origin) {
    Target.prototype = Origin.prototype;
}

inherit(Son, Father);
var son = new Son();
  1. 圣杯模式
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的原型

二十、深度克隆

  1. 遍历对象 for(var prop in obj)
  2. 判断是原始值还是引用值 typeof()
  3. 如果是引用值,判断是数组还是对象 instanceof toString constructor
  4. 建立相应的数组或对象
  5. 递归
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 = []

数组的常用方法

改变原数组的一类

  1. arr.push()

在数组的最后一位开始添加数据,可添加多位

  1. arr.pop()

把数组的最后一位剪切出去

  1. arr.shift()

从数组前面剪一位

  1. arr.unshift()

在数组前面添加数据,可添加多位

  1. arr.splice

arr.splice(从第几位开始, 截取的长度, 在切口处添加新的数据)

  1. arr.reverse

数组顺序反过来

  1. 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);
})

不改变原数组的一类

  1. arr.concat(arr1)

将arr1拼到arr后面,生成一个新的数组,可用变量接收,不改变原arr和arr1数组

  1. arr.toString()

把数组变成字符串,返回,不改变原数组

  1. arr.slice(从该位开始截取,截取到该位但不包含该位)

不改变原数组,不写参数就是截取整个数组

  1. arr.join(参数)

将数组中的每个元素用传入的参数连接起来,并转换成字符串,不改变原数组

  1. 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的六种值对应的信息(错误类型):

  1. EvalError:eval()的使用与定义不一致
  2. RangeError:数值越界
  3. ReferenceError:非法或不能识别的引用数值

没定义就用

  1. SyntaxError:发生语法解析错误

语法有问题

  1. TypeError:操作数类型错误
  2. URIError:URI处理函数使用不当

二十四、es5严格模式

use strict

不再兼容es3的一些不规则语法。使用全新的es5规范。

两种用法:

  1. 全局严格模式
  2. 局部函数内严格模式(推荐)

就是一行字符串,不会对不兼容严格模式的浏览器产生影响

二十五、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 //返回后一个/前一个兄弟元素

节点的四个属性

  1. nodeName

元素的标签名,以大写形式表示,只读

  1. nodeValue

Text节点或Comment节点的文本内容,可读写

  1. nodeType

该节点的类型,只读

  1. 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结构树

在这里插入图片描述

练习:

  1. 封装函数,返回元素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>
  1. 编辑函数,封装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>
  1. 自己封装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>
  1. 封装函数,返回元素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>

利用事件冒泡,和事件源对象进行处理

优点:

  1. 性能 不需要循环所有的元素一个个绑定事件
  2. 灵活 当有新的子元素时不需要重新绑定事件

事件分类

拖拽事件

<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异步加载的三种方案

  1. defer异步加载,你加载你的我加载我的,一起加载,但要等到dom文档全部解析完才会被执行。只有IE能用,也可以将代码写到内部。例:
    <script type="text/javascript" src="tools.js" defer="defer"></script>
  2. async异步加载,加载完就执行,async只能加载外部脚本,不能把js写在script标签里。例:
    <script type="text/javascript" src="tools.js" async="async"></script>
  3. 创建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();
    });

时间线

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值