JavaScript入门

JS介绍

// JavaScript的发明人
// 布兰登·艾奇(Brendan Eich),用了十天时间发明了JavaScript模型

// JavaScript简称JS

// JavaScript是什么?
// 1.脚本语言
// 编译语言:需要把代码编译成计算机所认知的二进制语言才能执行
// 脚本语言:不需要编译,直接执行
// 2.解释性语言
// 解释性语言:遇到一行代码就解释一行代码
// 其他语言:把所有代码编译完成后在执行代码
// 3.动态类型的语言
// 4.基于对象的语言
// 5.弱类型语言
// 弱类型语言:声明变量都用var,会自动辨别类型:var num = 10; var num2 = 10.23;
// 强类型语言:声明变量的时候必须写上对应变量的类型:int num = 10; double num2 = 10.23;

// JS分三个部分: 
// 1.ECMAScript js的基本语法
// 2.DOM  Document Object Model 文档对象模型
// 3.BOM Browser Object Model 浏览器对象模型

// js代码注意问题
// 1.如果script的标签中有错误的js代码,那么这对script标签就不会执行
// 2.如果有一个script标签代码错误,但它不会影响其他的script标签
// 3.script标签在页面中可以多对出现
// 4.script标签一般放在body标签内容的最后,可以放在head中
// 5.如果script标签引用外部js文件,那么就不要在这对标签里面放任何js代码

数据输出\输入

// 在浏览器弹出的提示框中显示
alert();
// 在浏览器的控制台中显示
console.log();
// 在浏览器页面中显示
document.write();
// 在浏览器中弹出输入框
prompt();

JS变量

/*什么是变量:
 变量是计算机内存中存储数据的标识符,根据变量名可以获取到内存中存储的数据*/

/*为什么使用变量:
 使用变量可以方便的获取或者修改内存的数据*/

// 变量的作用:
// 操作数据:存储数据、读取数据

/*变量名的规范:
一般以字母,$符号,下划线开头
变量名一般都是小写,如果是多个单词,那么第一个单词的首字母小写,后面的单词首字母大写
变量名不能是关键字
区分大小写*/

// 变量声明
var  name;// 有var 有变量名字但没有赋值

// 声明多个变量
var name,age,sex;

// 变量的初始化:声明变量同时赋值
var xiu = undefined;// 声明变量没有赋值默认为undefined:未定义
var number = 20;// 存储一个数字(number)
var name = "修抗";// 存储一个字符串(string) 字符串应该用单引号或者双引号包裹起来
var flag = true;// 存储一个真(true) 假(false)
var nll = null;// 存储一个空(null)

// 声明多个变量依次赋值
var num1,num2,num3;
num1 = 10;
num2 = 20;
num3 = 30;

// 声明多个变量并赋值
var num1 = 10,num2 = 20,num3 = 30;

// 变量的交换(1)
var num1 = 10,num2 = 20;
var num3;//重新声明一个变量
num3 = num1;//num3 = num1 = 10
num1 = num2;//num1 = num2 = 20
num2 = num3;//num2 = num3 = 10

// 变量的交换(2)一般适用于数字的交换
var num4 = 10,num5 = 20;
num4 = num4 + num5;//10+20=30
num5 = num4 - num5;//30-20=10
num4 = num4 - num5;//30-10=20

// 变量的交换(3)
var num6 = 10,num7 = 20;
num6 = num6 ^ num7;
num7 = num6 ^ num7;
num6 = num6 ^ num7;

JS数据类型

/*
原始数据类型:number,string,boolean,undefined,null,object
基本类型:number,string,boolean
复杂类型:object
空类型:undefined,null

基本类型的值在栈空间存储
复类类型的值在堆空间存储,然后在栈空间引用堆空间的地址
*/
// 获取变量的数据类型
var xiu = "修抗";
console.log(typeof(xiu)); //string

进制介绍

// 八进制(数字前面加一个0代表八进制)
var num = 012;

// 十进制
var num2 = 10;

// 十六进制(数字前面加一个0x代表十六进制)
var num3 = 0xa;

/*二进制-->十进制
1----1----0----0----1----0----1----0----1(二进制)
256--128--64---32---16---8----4----2----1
256--128--0----0----16---0----4----0----1(十进制)
二进制:110010101 = 256+128+0+0+16+0+4+0+1 = 405:十进制
*/ 

/*二进制-->八进制
110----010----101(二进制)
6------2------5(八进制/每三位二进制为一组)
二进制:110010101 = 625:八进制
*/

/*二进制-->十六进制
1----1001----0101(二进制)
1----9-------5(十六进制/每四位二进制为一组)
二进制:110010101 = 195:十六进制
*/

/*十进制-->二进制
405-202-101-50--25--12--6---3---1
1---0---1---0---1---0---0---1---1(倒叙)
十进制:405 = 110010101:二进制
 */

数字(Number)

// 小数类型和整数类型都是数字类型(Number)

//数字的最大值和最小值
console.log(Number.MAX_VALUE);//最大值
console.log(Number.MIN_VALUE);//最小值

// Infinity 无穷大
// -Infinity 无穷小

// 小数的bug
console.log(0.1+0.2);//结果不是0.3而是0.30000000000000004

// 不要用NaN验证NaN
var xiu;
console.log(xiu+10);//返回NaN
console.log("你好" == "我好");//false:都是字符串,但是字符串内容不一样
console.log(xiu+10 == NaN);//false:都是NaN,但是里面的值不一样

// isNaN()判断是否不是数字,如果不是数字返回true
console.log(isNaN(NaN));

字符串(String)

// 字符串可以使用单引号,也可以使用双引号
var str = "xiu ";
var str2 = 'kang';

// 查看字符串的长度
console.log(str.length);

// 字符串拼接,用+链接
// 如果两边只要有一边为字符串,那么+就为拼接
// 如果两边都是数字。那么就是算术功能
var str3 = "1";
var str4 = '2';
console.log(str3 + str4);//12

Boolean类型/Undefined类型/Null类型

// Boolean类型
// 布尔类型只有两个值 true(真) false(假)
var flag = true;

// Undefined
// 表示声明一个变量没有赋值,变量只有声明的时候值默认为undefined
var unde = undefined;

// null类型
// 表示一个空,变量的值如果为空,必须手动设置
var str = null;

类型转换

// 其他类型转为数字类型:三种方式
// parseInt();转整数
console.log(parseInt("8sa"));//8
console.log(parseInt("as8"));//NaN
console.log(parseInt("8.9"));//8
console.log(parseInt("8.2as"));//8
console.log(parseInt("sa6.8"));//NaN

// parseFloat();转小数
console.log(parseFloat("8sa"));//8
console.log(parseFloat("as8"));//NaN
console.log(parseFloat("8"));//8
console.log(parseFloat("8.9as"));//8.2
console.log(parseFloat("sa6.8"));//NaN

// Number();转数字
console.log(Number("8sa"));//NaN
console.log(Number("as8"));//NaN
console.log(Number("8"));//8
console.log(Number("8.9as"));//NaN
console.log(Number("sa6.8"));//NaN

// 其他类型转为字符串类型:两种方式
// toString;不能转换没有意义的变量:null、undefined
var xiu = 10;
console.log(xiu.toString());

// String();
var kang = 20;
console.log(String(kang));

// 其他类型转为布尔类型
// Boolean();
console.log(Boolean(0));//false
console.log(Boolean(""));//false
console.log(Boolean(null));//false
console.log(Boolean(undefined));//false

运算符

// x+y
// x和y是操作数 +是操作符

// 算术运算符(+、-、*、/、%)
10%4;//10除于4的余数

// 一元运算符(++、--)
// 这个运算符只需要一个操作数就可以运算的表达式
// 前+ 后+ 前- 后-
var x = 2;
var y = 2;
console.log(x++ +3);//5,后+,先参与运算,运算结束后在+1
console.log(x);//3
console.log(++y +3);//6,前+,先+1,然后在参与运算
console.log(y);//3

// 二元运算符()
// 这个运算符需要两个个操作数就可以运算的表达式

// 三元运算符()
// 这个运算符需要三个操作数就可以运算的表达式
// var 变量 = 表达式1 ? 表达式2 : 表达式3
// 如果表达式1结果为true,就执行表达式2,然后把表达式2的结果给变量
// 如果表达式1结果为false,就执行表达式3,然后把表达式3的结果给变量
var sear = true ? 1 : 2;//sear=1

// 复合运算符(+=、-=、*=、/=、%=)
var num;
num+=10;//num=num+10;

// 关系运算符(<、>、<=、>=、!=、==、===、!=、!==)
var xiu = "10";
var kang = 10;
console.log(xiu==kang);//两个值都一样所以为true
console.log(xiu===kang);//值一样,但是类型不一样所有为false

// 逻辑运算符($$与-并且、 ||或-或者、 !非-取反、)
console.log(true && true);//两个为true则为true
console.log(true || false);//一个为true则为true
console.log(!false);//false为true,true为false

/*
运算符的优先级
1.() 优先级最高
2.一元运算符 ++ -- !
3.算术运算符 先* / 后 + -
4.关系运算符 < <= > >=
5.相等运算符 == != === !==
6.逻辑运算符 先&& 在||
7.赋值运算符 =
 */

流程控制

// 流程控制:代码的执行过程

// 流程控制的三种方式:
// 1.顺序结构
// 从上到下,从左往右执行的顺序叫顺序结构(不严谨)
// var xiu = 2;(不严谨的原因:先找到2,然后在将2赋值给xiu)

// 2.分支结构

// if语句
/*
if(表达式1) {
    代码块1
}else if(表达式2) {
    代码块2
}else {
    代码块3
}
先运行表达式1,如果表达式1为true就执行的代码块1,如果为false就执行表达式2
如果表达式2,如果表达式2为true就执行的代码块2,如果为false就执行代码块3
else if()可以多次出现,也可以不写
else 只能出现一次,也可以不写
*/
var x = prompt("请输入数字");//prompt()弹出一个输入框
if(x > 5){
    console.log("大于5");
}else if(x < 5) {
    console.log("小于5");
}else if(x == 5) {
    console.log("等于5");
}else {
    console.log("请输入数字");
}

// switch-case
/*
switch(表达式){
    case 值1: 代码块;break;    
    case 值2: 代码块;break;    
    case 值3: 代码块;break;    
    default:代码4;   
}
获取表达式的值,然后和值依次比较,如果和值相等执行相对应的代码块,遇到break跳出switch语句
如果和值都不相等,那么就执行default语句
表达式的值跟case的值比较是严格模式的比较(===)
default可以省略
break可以省略:省略后不会跳出语句 会依次往下执行
 */
var y = prompt("请输入1到3的整数");
switch(y){
    case "1":console.log(y);
    break;//该语句为跳出语句
    case "2":console.log(y);
    break;
    case "3":console.log(y);
    break;
    default:console.log("请输入1到3的整数");
}

// 三元表达式

// 3.循环结构
// while
/*
var 变量 = 0;
while(条件){
    循环体;
    计数器;
}
如果条件为false,就不执行while大括号里面的内容
如果条件为true,就执行循环体,然后执行计数器,循环结束后计数器+1,然后又去判断条件,直到条件为false停止循环
*/
var xiu = 0;//计数器
while(xiu<10){
    console.log(xiu);//循环体
    xiu++;//计数器+1
}

// do-while
/*
do {
    循环体
}while(条件);
先执行循环体,然后在判断条件是否成立,如果为true继续执行循环体,然后在判断条件,直到条件为false跳出循环
*/
var kang = 0;
do {
    console.log(kang);
    kang++;
}while(kang<0);

// for
/*
for(表达式1;表达式2;表达式3;){
    循环体;
}
先获取表达式1的值,然后判断表达式2,如果为false跳出循环,如果为true就执行循环体然后在执行表达式3,然后继续执行表达式2,直到条件为false
*/
for (var i = 1; i <= 10; i++) {
    console.log(i);
}

 break与continue关键字

// break关键字
// 作用:在循环中使用,遇到break则跳出当前循环
while(true){
    console.log("修抗");
    break;//本来是一个死循环,但是遇到break就跳出循环,所有就执行一次
}

// continue关键字
// 作用:在循环中使用,遇到continue直接执行下次循环
// 输出10以内的奇数
var i = 0;
while(i<10){
    if(i%2==0){
        i++;
        continue;//如果为偶数就继续下次循环
    }
    document.write(i);
    i++;
}

数组(Array)

// 数组:存储一组有序的数据

// 作用:可以一次性存储多个数据

// 数组的定义:
/*
1.通过构造函数创建数组
var 数组名 = new Array();
var 数组名 = new Array(长度);
如果Array中只有一个值(整数),那么这个值就是该数组的长度(元素就个数)
如果有多个值,那么这些值就是该数组的数据(数组的长度就是有多少个值)
 */
var array = new Array();//创建一个空数组,没有数据
var array2 = new Array("25");//如果数组中没有数据,但有长度,那么数组的每个值就是undefined

/*
2.通过字面量的方式创建数组
var array = [];
 */
var array3 = [];//创建空数组
var array4 = [3,34,46,7];//创建数组并添加数据

/*
数组元素:就是数组中存储的数据
数组个数:就是数组中元素的个数
数组下标:从0开始,到数组长度减1结束
通过下标设置数组元素值:数组名[下标] = 值
通过下标访问数组元素值:数组名[下标]
 */

// 获取数组的长度
array.length;

// 注意: 数组中的数据类型可以不一样,但一般存储一样的数据,数组的长度可以任意改变
var array5 = [10,"哈哈",true,undefined,null,new Object()];

// 遍历数组
var array6 = [2,5,72,58,3,52];
for(var i=0;i<array6.length;i++){
    console.log(array6[i]);
}

// 求数组的和
var array7 = [1,2,3,4,5];
var sum = 0;
for(var i=0;i<array7.length;i++){
    sum+=array7[i];
}
console.log(sum);

// 求数组的平均值
var array8 = [1,2,3,4,5];
var avg = 0;
for(var i=0;i<array8.length;i++){
    avg+=array8[i];
}
console.log(avg/array8.length);

// 求数组的最大值
var array9 = [1,2,3,4,5];
var max = array9[0];
for(var i=1;i<array9.length;i++){
    if(max<array9[i]){
        max=array9[i];
    }
}
console.log(max);

// 数组的倒叙
var array10 = [1,2,3,4,5];
for(var i=array10.length-1;i>=0;i--){
    console.log(array10[i]);
}

// 去掉数组中的0
var array11 = [1,0,3,0,5];
var newArray11 = [];
for(var i=0;i<array11.length;i++){
    if(array11[i] != 0){ 
        newArray11[newArray11.length] = array11[i];
    }
}
console.log(newArray11);

// 冒泡排序:把所有数据按照一定顺序进行排序(从大到小,从小到大)
var arr = new Array(3,36,2,47,42,436,54);
for (var i=0;i<arr.length-1;i++) {
    for(var j=0;j<arr.length-1-i;j++){
        if(arr[j]>arr[j+1]){
            var tame = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = tame;
        }
    }
}
console.log(arr);

 函数(function)

/*
函数:将重复的代码进行封装,在需要的时候进行调用

定义函数:
function 函数名(){
    函数体;
}
调用函数:
函数名();

函数参数:
定义函数的时候,函数名后面的小括号里的变量就是参数
function 函数名(x,y){
    函数体;
}

形参:定义函数时小括号里面的参数
function 函数名(x,y){
    函数体;
}
实参:调用函数时小括号里面的参数
函数名(x,y);

函数的返回值:
在函数内部有return关键字并且关键字后面有内容,那么这个内容就是返回值
在调用的时候,如果需要返回值,就定义变量接收就行了
function 函数名(){
    return 520;
}
var fun = 函数名();//此时fun变量的值就是函数返回的值

无参数无返回值的函数
function xiu(){
    console.log("修抗");
}
无参数有返回值的函数
function xiu(){
    return "修抗";
}
有参数无返回值的函数
function xiu(x,y){
    console.log(x+y);
}
有参数有返回值的函数
function xiu(x,y){
    return x+y;
}

命名函数:函数有名字
匿名函数:函数没有名字

定义匿名函数:
function(){
    函数体;
}
匿名函数不能直接调用,需要赋值给变量才能调用(这就是函数表达式)
var fun = function(){
    函数体;
}
fun();//在变量后面添加小括号就可以调用匿名函数了

函数的自调用:
(匿名函数)();
(function(){alert("修抗");})();

函数做为参数使用:
如果一个函数作为参数使用,那么这个参数(函数)就是回调函数
function xiu(){
    kang();
}
function kang(){
    函数体;
}

函数做为返回值使用:
function xiu(){
    return function(){
        函数体;
    };
}
var kang = xiu();//将xiu的返回值赋值给变量,现在变量就是一个函数
kang();//直接加小括号掉用就行了

注意:
函数一旦重名,就会把前面的函数覆盖
匿名函数就不会出现重名的问题
形参和实参的个数可以不一致
函数没有明确返回值,但调用的时候接收了,那么接收的值为undefined
没有明确返回值:没有return或者return后面没有跟任何内容
return后面的代码不会执行
函数也有数据类型:function类型
 */

函数中的几个参数

function f1(x,y){
    //获取的函数的名字,只读
    console.log(f1.name);
    // 获取实参的个数
    console.log(f1.arguments.length);
    // 获取形参的个数
    console.log(f1.length);
    // 调用者,如果该函数被其他函数调用,那么该属性就输出其他函数的源码
    console.log(f1.caller);
}
f1(1,2);

 sort()

// sort()对数组的元素进行排序,并返回数组
var arr = ["dfg","dgh","dsgar"];
arr.sort(function(x,y){
    if(x>y){
        return 1;
    }else if(x==y){
        return 0;
    }else {
        return -1;
    }
});
console.log(arr);

闭包

/*
闭包的概念:
在函数A中有一个函数或者对象,该函数或者对象可以访问函数A中定义的变量或者数据,此时形成了闭包
闭包的模式:
函数模式的闭包,对象模式的闭包
闭包的作用:
缓存数据,延长作用域链
闭包的优点缺点:
优点:可以缓存数据,缺点:缓存数据的同时不能释放空间
局部变量是在函数中,函数使用结束后,局部变量就会被自动释放
闭包后,里面的局部变量的使用作用域就会被延长,不会被释放
 */
// 函数模式的闭包:在一个函数中有一个函数
function f1(){
    var num = 10;
    function f2(){
        console.log(num);
    }
    f2();
}
f1();
// 对象模式的闭包:在一个函数中有一个对象
function f3(){
    var num = 3;
    var obj = {age:num};
    console.log(obj.age);
}
f3();

// 列子:
function person(){
    var num = 1;
    return function(){
        num++;
        console.log(num);
    }
}
var per = person();
per();//2
per();//3
per();//4

沙箱

作用域

/*
局部变量:在函数内部定义的变量叫局部变量,只能在函数内部才能使用
全局变量:除了函数以外在其他任意位置定义的变量叫全局变量,可以在页面任意位置使用
隐式全局变量:声明变量的时候没有var就是隐式全局变量(可以在页面任意位置使用)

局部作用域:局部变量的使用范围
全局作用域:全局变量的使用范围
块级作用域:大括号里面定义的变量只能在当前大括号里面使用,而js不支持块级作用域(函数除外)

注意:
定义全局变量,只要页面不关闭就会一直占空间,消耗内存(就是卡),只有在页面隔壁的时候才会释放空间
定义局部变量,就只有在调用的时候占空间,调用完后就会释放空间(所以尽量使用局部变量)
全局变量不能被删除而隐式全局变量可以被删除,删除变量(delete 变量名;)

作用域链:
var sum = 0;
function f1(){
    var sum = 1;
    f2();
    function f2(){
        var sum = 2;
        f3();
        function f3(){
            var sum = 3;
            alert(sum);
        }
    }
}
如果当前没有变量就会去上一级找变量,没有继续去上一级,直到全局变量,这就是作用域链
 */

预解析

// 预解析:提前解析代码

// 提前解析变量
console.log(sum);//输出undefined
var sum = 0;
/*
理解:浏览器帮我们做的事,浏览器将声明变量提前了,但没有把赋值提前
var sum;
console.log(sum);//因为声明变量没有赋值,所以就是undefined
sum = 0;
 */

// 提前解析函数
xiu();
function xiu(){
    console.log("爱心");
}
/*
理解:浏览器帮我们做的事,浏览器将声明的函数提前了
function xiu(){
    console.log("爱心");
}
xiu();
 */

// 同时解析函数和变量
kang();
function kang(){
    console.log(str);
}
var str = "埃辛";
/*
理解:浏览器帮我们做的事,浏览器先将声明的变量提前然后在将声明的函数提前
var str;
function kang(){
    console.log(str);
}
kang();
str = "埃辛";
 */

函数声明出现的问题

/*
函数的声明
function f1(){}

函数表达式
var f1 = function(){};
 */
if(true){
    function f1(){
        console.log("true");
    }
}else {
    function f1(){
        console.log("false");
    }
}
f1();
// 在IE10及之前输出的结果都是false,因为会把函数的声明提前
// 解决办法就是使用函数表达式,函数表达式不会被提前
 var f2;
 if(true){
    f2 = function(){
        console.log("true");
    }
}else {
    f2 = function(){
        console.log("false");
    }
}
f2();

创建对象

/*
编程思想:
把一些生活中的经验融入到程序中

面向过程:
每件事的具体过程要知道,注重的是过程

面向对象:
所有的事都用对象来做,注重的是结果

面向对象的基本特性:
封装,继承,多态(抽象性)

对象的特征:
有属性或者方法

面向对象的编程思想:
根据需求,找出相关的对象,总结对象的特征和行为,把特征变成属性,行为变成方法,然后定义构造函数,实例化对象,通过对象调用属性或者方法,完成对应的需求,这就是编程思想 js不是面向对象的语言,但是可以模拟面向对象的思想 js是一门基于对象的语言
*/ // 第一种方式创建对象:调用系统自带的构造函数 new Object() var obj = new Object(); obj.name = "修抗"; //添加属性1 obj.sex = "男"; //添加属性2 obj.xiu = function(){ //添加方法1 console.log("方法1"); } obj.kang = function(){ //添加方法2 console.log("方法2"); } // 调用属性的两种方式 console.log(obj.name); //对象.属性 console.log(obj["sex"]); //对象["属性"] // 调用方法的两种方式 obj.xiu(); //对象.方法名() obj["kang"](); //对象["方法名"]() // 第二种方式创建对象:自定义一个构造函数,然后在创建对象 // 创建自定义构造函数,构造函数与函数的区别在于首字母是否大写 function Person(name,age){ //添加属性 this.name = name; this.age = age; //添加方法 this.type = function(){ console.log("我叫"+this.name+",今年"+this.age+"岁"); }; } //调用自定义的构造函数创建对象,同时对属性进行初始化(实例化对象) var obj2 = new Person("修抗",24); // 调用属性和方法 console.log(obj2.name); obj2.type(); // 第三种方式创建对象:工厂模式创建对象 // 把创建对象的代码放在函数中,返回值就是这个对象, function createObject(name,age){ var obj3 = new Object(); obj3.name = name; obj3.age = age; obj3.xiu = function(){ console.log("我叫"+this.name+",今年"+this.age+"岁"); } return obj3; } var kang = createObject("修抗",20); kang.xiu(); // 第四种方式创建对象:字面量创建对象 // 方式1: var obj4 = {}; obj4.name = "修抗";// 添加属性 obj4.type = function(){// 添加方法 alert("方法"); } // 方式2: var obj5 = { name: "修抗", type:function(){ alert("方法2") } };

遍历对象的属性和值

var obj = {
    name : "修抗",
    age : 20
}
for(key in obj){
    console.log(key);//属性
    console.log(obj[key]);//
}

工厂模式和自定义构造函数的区别

// 自定义创建对象
function Penson(name){
    this.name = name;
}
var obj = new Penson("修抗");
console.log(obj.name);

//工厂模式创建对象
function createObj(){
    var obj2 = new Object();
    obj2.name = "爱心";
    return obj2;
}
var obj3 = createObj();
console.log(obj3.name);
/*
自定义创建对象与工厂模式创建对象的区别

自定义创建对象:
函数名是大写(首字母)
没有new
没有返回值
this是当前对象
通过new的方式创建对象

工厂模式创建对象:
函数名是小写
有new
有返回值
new之后的对象是当前对象
直接调用函数就可以创建对象

他们的共同点:都是函数,都可以创建对象,都可以传入参数
 */

构造函数和实例对象之间的关系

// 自定义构造函数创建对象
function Person(name){
    this.name = name;
 }
 //实例化对象
var obj = new Person("修抗");
// console.dir()可以把对象的构造显示出来
console.dir(Person);//输出构造函数
console.dir(obj);//输出实例化对象
console.log(Person.prototype.constructor == Person);//true
console.log(obj.__proto__.constructor == Person);//true
console.log(obj.constructor == Person);//true
console.log(obj instanceof Person);//true
/*
实列对象和构造函数的关系
实列对象是通过构造函数来创建的,创建的过程叫实例化
判断对象的数据类型(自定义对象)
1. 通过构造器的方式:
实列对象.构造器(constructor) == 构造函数的名字
obj.constructor == Person
2. 对象 instanceof 构造函数名字
obj instanceof Person
 */

构造函数创建对象带来的问题

function Person(name,age){
    this.name = name;
    this.age = age;
    this.type = function(){
        console.log("修抗");
    }
}
var obj1 = new Person("修抗",20);
var obj2 = new Person("修抗",20);
// 他们指向的方法不是同一个方法,那么就开辟了不同的空间,浪费内存
console.log(obj1.type == obj2.type);//false
// 解决办法
function f1(){
    console.log("修抗");
}
function Person2(name){
    this.name = name;
    this.type = f1;
}
var obj3 = new Person2("修");
var obj4 = new Person2("修");
// 此时他们指的是同一个方法,节省空间,但函数可能重名,发生不必要的问题
console.log(obj3.type == obj4.type);//true
// 可以使用原型解决该办法:原型的作用之一就是数据共享,节省内存空间

原型及原型链

//构造函数
function Person(name,age){
    this.name = name;
    this.age = age;
}
// 实例化对象并初始化
var p1 = new Person("修抗",20);
var p2 = new Person("爱惜",20);
console.dir(Person);//查看构造函数的结构
console.dir(p1);//查看实列对象的结构
/*
实列对象中有两个属性(这两个属性是通过构造函数获取的)
构造函数中并没有name和age这两个属性

实列对象中有个属性,__proto__,也是对象,叫原型,不是标准属性,浏览器使用的
构造函数中有个属性,prototype,也是对象,叫原型,是标准属性,程序员使用的

constructor:构造函数
*/
// 实列对象和构造函数的原型指向的是同一个构造函数
console.log(Person.prototype.constructor == p1.__proto__.constructor);//true
// 通过原型添加方法
Person.prototype.type = function(){
    console.log("修抗");
}
// 因为他们指向的是同一个原型里面的构造函数里面的方法,是同一个方法
console.log(p1.type == p2.type);//true

// 原型链:是一种关系,实列对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的

改变原型的指向和添加改变后的原型方法

function Person(){};
Person.prototype.sayHi = function(){
    console.log("打招呼");
};
function Student(){};
Student.prototype.eat = function(){
    console.log("牛皮");
};
Student.prototype = new Person();
var obj = new Student();
obj.sayHi();
// obj.eat();//报错
/*
实列对象的原型__proto__指向的是该对象所在的构造函数的原型对象
构造函数的原型对象(prototype)指向如果改变了,实列对象的原型(__proto__)指向也会发生改变
实列对象和原型对象之间的关系是通过__proto__原型来联系起来的,这个关系就是原型链
 */

原型链最终的指向

function Person(){};
Person.prototype.sayHi = function(){
    console.log("打招呼");
};
var obj = new Person();
console.dir(Person);

// 实列对象中__proto__原型
// 构造函数中prototype原型
// 实列对象的原型和构造函数的原型指向是同一个地方
console.log(Person.prototype == obj.__proto__);//true
// prototype是对象,那么对象就有原型 __proto__
// 实列对象中的__proto__原型指向的是构造函数的prototype
// 构造函数的prototype的__proto__的指向是Object的prototype
console.log(Person.prototype.__proto__ == Object.prototype);//true
//Object的prototype的指向就是null
console.log(Object.prototype.__proto__);//null

 原型列子

<div id="dv"></div>
<input type="button" id="btn" value="按钮"/>
<script>
    function Person(btnObj,dvObj,json){
        this.btnObj = btnObj;
        this.dvObj = dvObj;
        this.json = json;
    }
    Person.prototype.inio = function(){
        var that = this;
        this.btnObj.onclick = function(){
            // 当前this为按钮对象,所以需要在外面添加一个this变量
            for(var key in that.json){
                that.dvObj.style[key] = json[key];
            }
        }
    }
    var dv = document.getElementById("dv");
    var btn = document.getElementById("btn");
    var json = {"width":"200px","height":"400px","backgroundColor":"red"};
    //大概意思就是把添加样式的代码封装在构造函数中,方法在原型中添加
    //点击按钮为id节点设置多个样式
    var obj = new Person(btn,dv,json);
    obj.inio();
</script>

构造函数,实列对象,原型对象之间的区别

// 构造函数
function Person(name,age){
    this.name = name;
    this.age = age;
}
// 通过构造函数创建实列对象,并初始化
var obj = new Person("修抗",20);
// 构造函数里面的prototype属性指向的是构造函数里面的原型
// 通过构造函数为原型添加一个方法
Person.prototype.type = function(){
    console.log("方法");
}
// 原型对象里面的constructor指向的是自己所在的原型对象所在的构造函数中
console.log(Person.prototype.constructor);//输出的是Person构造函数
// 实列对象里面的__proto__属性指向构造函数里面的原型的方法
obj.__proto__.type();//调用原型里面的方法
// 构造函数的原型对象中的方法可以被实例化对象直接访问
obj.type();//调用原型里面的方法

构造函数的属性或者方法的搜索方式

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.name = "修抗";
var obj = new Person("小子",20);
console.log(obj.name);//修抗
/*
实列对象使用属性或者方法,
先在实列中查找,有则直接使用,
无则去实列对象的__proto__指向的原型对象prototype中找,有则使用,没有则报错
 */ 

为内置对象的原型对象添加方法

console.dir(Array);
//内置对象的方法一般都在该构造函数指向的原型中
// 那么就可以通过构造函数的原型添加内置对象的方法
Array.prototype.mySort = function(){
    for (var i = 0; i < this.length-1; i++) {
        for (var j = 0; j < this.length-1-i; j++) {
            if(this[j]>this[j+1]){
                var time = this[j];
                this[j] = this[j+1];
                this[j+1] = time;
            }
        }
    }
}
var arr = [3,51,543,62,31,5];
// 使用自定义的内置方法
arr.mySort();
console.log(arr);

局部变量变成全局变量

//函数自调用
// (function(){
//     var num = 10;
// })();
// console.log(num);//报错,因为num是局部变量,无法在函数外使用

(function(){
    var num = 10;
    // js是一门动态类型的语言,对象没有属性,点了就有了
    // window是浏览器的顶级对象
    window.num = num;
})();
console.log(window.num);//10
console.log(num);//10

原型及原型链

function Person(){};
Person.prototype.sayHi = function(){
    console.log("打招呼");
};
function Student(){};
Student.prototype.eat = function(){
    console.log("牛皮");
};
Student.prototype = new Person();
var obj = new Student();
obj.sayHi();
// obj.eat();//报错
/*
实列对象的原型__proto__指向的是该对象所在的构造函数的原型对象
构造函数的原型对象(prototype)指向如果改变了,实列对象的原型(__proto__)指向也会发生改变
实列对象和原型对象之间的关系是通过__proto__原型来联系起来的,这个关系就是原型链
 */

继承

/*
面向对象的基本特性

封装:
把一个值放在变量中叫封装
把重复的代码放在函数中叫封装
把重复的属性放在对象中叫封装
把功能类似的函数(方法)放在对象中叫封装
把类似的对象放在一个js文件中叫封装

继承:
面向对象的编程语言中有类(class)的概念,但是js不是面向对象的语言,所以js中没有类,但是js可以模拟面向对象的思想编程,js会通过构造函数来模拟类的概念
首先继承是一种关系,类与类之间的关系,js通过构造函数模拟类,然后通过原型来实现继承
继承是为了数据共享,js中的继承也是为了实现数据的共享
继承的关系:父类与子类的关系

多态:
一个对象有不同的行为,或者是同一个行为针对不同的的对象产生不同的结果,想要有多态,就要先有继承js中可以模拟多态,但不会使用,也不会模拟,因为数据不能共享,会占用大量内存空间
 */

// 原型的作用之一:数据共享,节省内存空间
// 原型的作用之二:为了实现继承

/*
列子:
Person的数据共享给Student就叫继承
 */
function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.type = function(){
    console.log("玩");
}
function Student(score){
    this.score = score;
}
// 通过改变原型的指向来模拟继承
Student.prototype = new Person("小明",20);
Student.prototype.Study = function(){
    console.log("学习");
}
var stu = new Student("100");
// 人的方法和属性
console.log(stu.name);//小明
console.log(stu.age);//20
stu.type();//
// 学生的方法和属性
console.log(stu.score);//100
stu.Study();//学习
// 优点:继承了方法和属性
// 缺陷:改变原型指向的同时赋值了,那么子类调用的时候直接使用了父类初始化的属性

借用构造函数继承

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.type = function(){
    console.log("玩");
}

function Student(score,name,age){
    Person.call(this,name,age);
    this.score = score;
}
Student.prototype.study = function(){
    console.log("学习");
}
var obj = new Student(20,"小明",30);
console.log(obj.score);//20
console.log(obj.name);//小明
console.log(obj.age);//30
obj.study();
/*
借用构造函数:
把继承父类的构造函数拿过来使用

借用构造函数:构造函数的名字.call(当前对象,属性,属性...)
解决了属性继承,并且值不重复的问题
缺陷,无法继承父类的继承
 */

组合继承

/*
原型实现继承
借用构造函数实现继承
组合继承:原型继承+借用构造函数继承
 */
function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.sayHi = function(){
    console.log("打招呼");
}
function Student(score,naem,age){
    // 借用构造函数实现继承
    Person.call(this,name,age);
    this.score = score;
}
// 改变原型的指向
Student.prototype = new Person();
Student.prototype.eat = function(){
    console.log("玩耍");
}
var obj = new Student(10,20,100);
console.log(obj.name);
console.log(obj.age);
console.log(obj.score);
obj.sayHi();
obj.eat();
// 优点:父类的属性和方法都被继承了

apple()与call()

/*
apply()和call()的作用: 改变this的指向
使用语法:
函数名字.apply(对象,[参数1,参数2...]);
方法名字.apply(对象,[参数1,参数2...]);
函数名字.call(对象,参数1,参数2...);
方法名字.call(对象,参数1,参数2...);
 */
// 修改函数的this指向
function f1(x,y){
    console.log((x+y)+"..."+this);
}
// "use strict";//严格模式
// 在严格模式下,如果没有window,this指向为undefined
// window.f1(1,2);//3...undefined
f1(1,2);//3...window
var obj = new Object();
// 通过apple或者call改变函数中的this指向
f1.apply(obj,[1,2]);//3...Object

// 修改方法的this指向
function Person(age){
    this.age = age;
}
Person.prototype.sayHi = function(x,y){
    console.log((x+y)+"..."+this.age);
}
function Stuendt(age){
    this.age = age;
}
var per = new Person(10);
var stu = new Stuendt(20);
// sayHi是per的实列对象
// 通过apple或者call改变了this的指向
per.sayHi.apply(stu,[1,2]);//3...20(此时的this.age是stu实列对象中的this)
per.sayHi.call(stu,1,2);//3...20

bind()

/*
bind的作用:复制一份然后在改变this的指向
使用语法:
函数名字.bind(对象,参数1,参数2...);返回值是复制后的这个函数
方法名字.bind(对象,参数1,参数2...);返回值是复制后的这个方法
 */

// 修改函数的this指向
function f1(x,y){
    console.log((x+y)+"..."+this);
}
f1(1,2);//3...window
var obj = new Object();
// 复制一份的时候,把参数传入到f1函数中,x-->1,y-->2,obj就是this,默认为window
// bind方法是复制的意思,参数可以在复制的时候传进去,也可以在复制之后传进去
var ff = f1.bind(obj);
ff(1,2);//3...Object

// 修改方法的this指向
function Person(age){
    this.age = age;
}
Person.prototype.sayHi = function(x,y){
    console.log((x+y)+"..."+this.age);
}
function Stuendt(age){
    this.age = age;
}
var per = new Person(10);
var stu = new Stuendt(20);
// sayHi是per的实列对象
var pers = per.sayHi.bind(stu,1,2);//此时的this.age是stu实列对象中的this
pers();//3...20

函数也是对象

function f1(){
    console.log("哈哈");
}
// f1是函数,也是对象
console.dir(f1);
// 对象调用方法,说明该对象有这个方法
f1.call();
f1.apply();
// 所用的函数都是Function的实列对象
console.log(f1.__proto__ == Function.prototype);//true

// 在构造函数Function的原型中就有call()和apply()方法
console.dir(Function);

拷贝继承

// 拷贝继承:把一个对象的属性或者方法复制到另外一个对象中
var obj = {
    name : "小明",
    type : function(){
        console.log("修抗");
    }
};

// 方式1:
//  改变的地址指向
var obj2 = obj;
console.log(obj2.name);
obj2.type();

// 方式2:
// 通过for循环遍历对象依次赋值给新对象
var obj3 = {};
for(var key in obj){
    obj3[key] = obj[key];
}
console.log(obj3.name);
obj3.type();

function Person(){};
Person.prototype.age = 10;
Person.prototype.play = function(){
    console.log("xiu");
}
// 方式3:
// 拷贝原型中的方法及属性
var obj4 = {};
for(var key in Person.prototype){
    obj4[key] = Person.prototype[key];
}
console.log(obj4.age);
obj4.play();

 内置对象

// 内置对象:自带的对象
// 在线文档(百度MDN):https://developer.mozilla.org/zh-CN/
// 常见的内置对象:
/*
全局对象
Infinity--无穷大
escape()--加密字符串
unescape()--解码字符串
encodeURI()--加密字符串为URI
decodeURI()--为加密的URI进行解码
encodeURIComponent()--将字符串加密为URI组件
decodeURIComponent()--为加密的URI组件解码
isFinite(number)--判断一个值是否是数字
isNaN(string)--判断一个值是否不是数字
Number(string)--将一个值转换为数字
parseFloat(string)--将一个值转换为小数
parseInt(string)--将一个值转换为整数
String(string)--将一个值转换为字符串
Boolean(string)--将一个值转换为布尔
*/
/*
Number对象
MAX_VALUE--最大数字
MIN_VALUE--最小数字
NaN--非数字
*/
/*
Boolean对象
toString()--将布尔值转换为字符串,并且返回结果
*/
/*
String对象
length--返回字符串的字符长度
fontcolor(color)--设置字符串的颜色(<FONT COLOR=>)
Fontsize(size)--设置字符串的大小(<FONTSIZE=>)
italics()--设置字符串的斜字体(<I>)
Link(url)--设置字符串的a标签(<A HREF=>)
strike()--设置字符串的删除线(<STRIKE>)
sub()--设置字符串的下标(subscript)字体((SUB>)
sup()--设置字符串的上标(superscript)字体(<SUP>)
charAt(index)--返回指定索引处的字符
concat(string2)--连接两条或多条字符串
indexOf(searchString, startIndex)--返回字符串中第一个出现指定字符串的位置
lastlndexOf(searchString, startIndex)--返回字符串中最后一个出现指定字符串的位置
match(regex)-- 在字符串中查找指定值
replace(regex, newString)--将字符串中的某些字符替换成其它字符
slice(startIndex, endIndex)--将部分字符抽出并在新的字符串中返回剩余部分
split(delimiter)--将字符串分配为数组
substr(startIndex, length)-- 从startIndex取,取length个字符
substring(startIndex, endIndex)-- 从startIndex和endIndex之间的字符,不包括endIndex
toLowerCase()-- 把字符串中的文本变成小写
toUpperCase()-- 把字符串中的文本变成大写
*/
/*
Array对象
length--获取数组元素的个数,即最大下标加1
concat(array1,arrayn)--合并数组,合并后返回结果
join(string)--将数组中元素合并为字符串,string为分隔符.如省略参数则直接合并,不再分隔
shift()--移除数组中的第一个元素并返回该元素
pop()--移除数组中的最后一个元素并返回该元素
unshift(value)为数组的开始部分加上一个或多个元素,并且返回该数组的新长度
push(value)--在数组的末尾加上一个或多个元素,并且返回新的数组长度值
reverse()--反转数组
sort()--按照元素的字母顺序排列,如果不是字符串类型则转换成字符串再排序,返回排序后的数组
toString()--将数组所有元素返回一个字符串,其间用逗号分隔
*/
/*
9.Date对象
getDay()--返回一周中的第几天(0-6)
getFullYear()--返回完整的4位年份数
getMonth()--返回月份数(0-11)
getDate()--返回日(1-31)
getHours()--返回小时数(0-23)
getMinutes()--返回分钟(0-59)
getSeconds()--返回秒数(0-59)
getMilliseconds()--返回毫秒(0-999)
toString()--将日期对象转换为字符串
*/
/*
Math对象
PI--∏的值(约等于3.14159)
abs(x)--返回数字的绝对值
ceil(x)--返回 x 四舍五入后的最大整数
floor(x)--返回 x 四舍五入后的最小整数
max(x,y)--返回 x 和 y 之间较大的数
min(x,y)--返回 x 和 y 之间较小的数
pow(x,y)--返回 y^x 的值
random()--返回位于 0 到 1 之间的随机函数
round(x)--四舍五入后取整
*/

 基本包装类型

// 普通变量不能直接调用属性或者方法
// 对象可以直接调用属性或者方法

// 普通变量在执行代码的过程中调用的属性或者方法,那么此时的普通类型就变成了基本包装类型,此时的变量就是基本包装类型对象

// 基本包装类型有number,string,boolean

var str = "修抗";//普通变量
str = str.replace("抗","康");//基本包装类型

var num = 10;//基本类型
var num2 = Number("10");//类型转换
var num3 = new Number("10");//基本包装类型

// 如果一个对象&&true,那么结果为true
// 如果一个true&&对象,那么结果为对象
var fleg = new Boolean(false);
console.log(fleg&&true);//true
console.log(true&&fleg);//function

 DOM介绍

// DOM:文档对象模型

// DOM就是把HTML看作一个文档,然后用DOM操作这些标签

// 文档(document):一个网页可以成为文档

// 元素(element):页面中所有的标签都是元素,元素可以看作一个对象

// 节点(node):页面中所有内容都是节点:标签,属性,文本

// 属性:标签的属性

// 根(root)

// 文档及文档中的所有元素组成一个树形结构图:树状图(DOM树)

为元素注册事件

<!-- 
要求:为按钮添加一个点击事件
事件源:button
事件名字:onclick
触发事件:点击时
响应:alert('...')
-->
<!-- 第一个版本 --> <!-- html代码中嵌入js代码:不方便后期修改和维护 --> <button onclick="alert('第1个版本')">按钮1</button> <!-- 第二个版本 --> <!-- js代码很多,但是没有与js分离,只是把js写入函数中,调用就行了 --> <button onclick="xiu()">按钮2</button> <script> function xiu(){ alert("第2个版本"); } </script> <!-- 第三个版本 --> <!-- js与html分离 --> <button id="sear">按钮3</button> <script> // 获取id为sear的标签,标签就是元素,元素就是对象 var searObj = document.ElementById(sear);//返回一个元素对象 searObj.onclick = function(){ alert("第3个版本"); } </script>

DOM获取元素的方法

<!-- 
根据id属性的值获取元素,返回来的是一个元素对象
document.getElementById("id的值"); 
-->
<a href="#" id="av">百度</a>
<input type="button" value="修改a标签的href属性值" id="but1"/>
<script>
    // 要求:点击按钮修改a标签的href属性值
    // 先通过id获取按钮并添加点击事件(onclick)
    document.getElementById("but1").onclick = function(){
        // 然后在获取a标签并修改href属性的值
        // 注:用DOM获取的标签就是元素,元素就是对象,可以通过对象修改属性的值
        document.getElementById("av").href = "http://www.baidu.com";
    }
</script>

<!-- 
根据标签名字获取元素,返回来的是一个伪数组,里面保存了多个DOM对象
document.getElementsByTagName("标签的名字"); 
-->
<p>段落</p>
<p>段落</p>
<p>段落</p>
<input type="button" value="修改所有p标签的内容" id="but2"/>
<script>
    // 要求:点击按钮修改所有p标签的内容
    // 先通过id获取按钮并添加点击事件(onclick)
    document.getElementById("but2").onclick = function(){
        // 然后获取所有的p标签并修改其内容
        var pObj = document.getElementsByTagName("p");//是一个伪数组,数组里面的元素就是p标签
        // 是一个伪数组,所以需要for循环遍历
        for(var i=0;i<pObj.length;i++){
            // 小提示:凡是成对的标签设置文本内容都使用innerText
            pObj[i].innerText = "修改";
        }
    }
</script>

<!-- 
根据name属性的值获取元素,返回来的是一个伪数组,里面保存了多个DOM对象
document.getElementsByName("name的值"); 
-->
<input type="button" value="修改name='xiu'的value值" id="but3"/>
<input type="text" value="你好" name="xiu"/>
<input type="text" value="你好" name="kang"/>
<input type="text" value="你好" name="xiu"/>
<script>
    // 要求:点击按钮修改name='xiu'的value值
    // 先通过id获取按钮并添加点击事件(onclick)
    document.getElementById("but3").onclick = function(){
        var xiuObj = document.getElementsByName("xiu");//是一个伪数组
        for(var i=0;i<xiuObj.length;i++){
            // 小提示:在文本框中设置文本值就是设置value值
            xiuObj[i].value = "修改";
        }
    }
</script>

<!-- 
根据类样式的名字来获取元素,返回来的是一个伪数组,里面保存了多个DOM对象
document.getElementsByClassName("class的值"); 
-->
<input type="button" value="修改class='xiu'的文本值" id="but4"/>
<span class="xiu">修抗</span>
<span>修抗</span>
<span class="xiu">修抗</span>
<script>
    // 要求:点击按钮修改class='xiu'的文本值
    // 先通过id获取按钮并添加点击事件(onclick)
    document.getElementById("but4").onclick = function(){
        var classObj = document.getElementsByClassName("xiu");//是一个伪数组
        for(var i=0;i<classObj.length;i++){
            classObj[i].innerText = "修改";
        }
    }
</script>

<!-- 
根据选择器获取元素,返回来的是一个元素对象
document.querySelector("选择器的名字"); 
-->
<input type="button" value="修改id='dv'的样式" id="but5"/>
<div id="dv"></div>
<script>
    // 要求:点击按钮修改id='dv'的样式
    // 先通过id获取按钮并添加点击事件(onclick)
    document.getElementById("but5").onclick = function(){
        document.querySelector("#dv").style.width = "300px";
        document.querySelector("#dv").style.height = "300px";
        // 在css中属性是多个单词的写法,那么在js操作DOM的时候,不要-,后面的单词首字母大写
        // background-color: red;(css)
        // backgroundColor = "red";(js) 
        document.querySelector("#dv").style.backgroundColor = "red";
    }
</script>

<!-- 
根据选择器获取元素,返回来的是一个伪数组,里面保存了多个DOM对象
document.querySelectorAll("选择器的名字");
 -->
<input type="button" value="修改所有p标签的内容" id="but6"/>
<div class="kang">修抗</div>
<div class="kang">修抗</div>
<div class="kang">修抗</div>
<script>
    // 要求:点击按钮修改class='kang'的文本值
    // 先通过id获取按钮并添加点击事件(onclick)
    document.querySelector("#but6").onclick = function(){
        var kangObj = document.querySelectorAll(".kang");//是一个伪数组
        for (var i = 0; i < kangObj.length; i++) {
            kangObj[i].innerText = "aixin";
        }
    }
</script>

操作DOM的案例(0)

<!-- 点击按钮显示和隐藏文字 -->
<input type="button" value="隐藏" id="but"/>
<p id="xiu">修抗</p>
<script>
//小提示:如果操作DOM的id属性有点多,那么可以将这个DOM操作封装起来,直接调用
function my$(id){
    return document.getElementById(id);
}
my$("but").onclick = function(){
    if(this.value == "隐藏"){
        my$("xiu").style.display = "none";//隐藏
        this.value = "显示";
    }else if(this.value == "显示"){
        my$("xiu").style.display = "block";//显示
        this.value = "隐藏";
    }
}
</script>

操作DOM的案例(1)

<!-- 点击按钮选中单选框/复选框(表单操作) -->
<input type="button" value="修改性别" id="but"/>
<input type="radio" value="男" name="sex" /><input type="radio" value="女" name="sex"/><!-- 
checked="checked":选中
在表单标签中,如果属性和值只有一个时,并且这个值就是这个属性本身
那么在html中,值可以默认不写:checked
在js的DOM操作的时候,值为布尔类型:checked = true
-->
<script>
    document.getElementById("but").onclick = function(){
        var radioObj = document.getElementsByTagName("input");
        if(radioObj[1].checked == false){
            radioObj[1].checked = true;
        }else if(radioObj[1].checked == true){
            radioObj[2].checked = true;
        }
    }
</script>

操作DOM的案例(2)

<!-- 点击按钮为div添加class属性(css样式操作) -->
<style>
    .cls {
        width: 100px;
        height: 100px;
        border: 1px solid red;
    }
</style>
<input type="button" value="按钮" id="but"/>
<div id="xiu"></div>
<script>
    // <div id="xiu" class="cls"></div>
    // 在js代码中操作DOM的时候,设置元素的类样式时,不能使用class关键字,应该使用calssName
    document.getElementById("but").onclick = function(){
        document.getElementById("xiu").className = "cls";
    }
</script>

操作DOM的案例(3)

<!-- 点击按钮隔行换色 -->
<input type="button" value="按钮"  id="but"/>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>
<script>
document.querySelector("#but").onclick = function(){
    var list = document.querySelectorAll("li");
    for(var i=0;i<list.length;i++){
        list[i].style.backgroundColor = i%2==0 ? "yellow" : "red"; 
    }
}
</script>

操作DOM的案例(4)

<!-- 高亮效果(css的hover效果) -->
<ul id="uu">
    <li>1</li>
    <li>2</li>
</ul>
<script>
    // onmouseover:鼠标进入事件
    // onmouseout:鼠标移出事件
    // 先获取id='uu'里面的li标签,是一个伪数组
    var listObj = document.getElementById("uu").getElementsByTagName("li");
    for (var i = 0; i < listObj.length; i++) {
        listObj[i].onmouseover = function(){
            this.style.backgroundColor = "red";
        }
        listObj[i].onmouseout = function(){
            this.style.backgroundColor = "";
        }
    }
</script>

操作DOM的案例(5)

<!-- 模拟搜索框的效果 -->
<input type="text" value="请输入搜索内容" id="txt" style="color:gray" />
<script>
    // onfocus获取焦点
    // onblur失去焦点
    var txt = document.getElementById("txt");
    txt.onfocus = function(){
        if(this.value == "请输入搜索内容"){
            this.value = "";
            this.style.color = "#000";
        }
    }
    txt.onblur = function(){
        if(this.value.length == 0){
            this.style.color = "gray";
            this.value = "请输入搜索内容";
        }
    }
</script>

操作DOM的案例(6)

<!-- 点击验证文本框的长度是否合法 -->
<input type="text" id="txt" />
<input type="button" id="but"  value="按钮"/>
<script>
    document.getElementById("but").onclick = function(){
        var txtObj = document.getElementById("txt");
        if(txtObj.value.length>3 && txtObj.value.length<6){
            alert("YES");
        }else {
            alert("NO:账号长度应该大于3并且小于6,当前长度为"+txtObj.value.length );
        }    
    }
</script>

修改标签中的文本内容

<!-- 
textContent
作用:为标签设置或者调用文本内容
谷歌火狐支持,IE8不支持
 -->
 <!-- 要求:修改p标签里面的内容 -->
 <input type="button" value="按钮" id="btn1">
 <p>爱心</p>
 <script>
 document.querySelector("#btn1").onclick = function(){
     document.querySelectorAll("p")[0].textContent = "修抗";
 }
 </script>

<!-- 
innerText
作用:为标签设置或调用文本内容
低版本的谷歌火狐不支持,IE8支持
 -->
 <!-- 要求:修改p标签里面的内容 -->
 <input type="button" value="按钮" id="btn2">
 <p>爱心</p>
 <script>
 document.querySelector("#btn2").onclick = function(){
     document.querySelectorAll("p")[1].innerText = "修抗";
 }
 </script>

<!-- 
因为不同浏览器支持的属性不一样
所以需要设置兼容代码
原理:如果浏览器不支持该属性,那么该属性的类型为 undefined
-->
<script>
    function setInnerText(elen,txt){
        if(typeof elen.innerText != "undefined"){
            elen.innerText = txt;
        }else {
            elen.textContent = txt;
        }
    }
    document.querySelector("#btn1").onclick = function(){
         setInnerText(document.querySelectorAll("p")[0],"修改");
     }
    
</script>

innerText与innerHTML的区别:

<!-- 
innerText 
主要用于设置文本,如果设置标签内容是没有标签效果的
可以获取标签里面的所有文本内容,但是不能获取标签
innerHTML 
可以设置文本内容,也可以设置HTML标签的内容
可以获取标签里面的所有文本内容,也可以获取里面标签
 -->
<input type="button" value="按钮" id="but"/>
<input type="button" value="按钮" id="but2"/>
<div id="dv">
    修抗
    <p>爱惜</p>
</div>
<script>
    function my$(id){
        return document.getElementById(id);
    };
    my$("but2").onclick = function(){
        // my$("dv").innerText = "<p>修抗<p>";//页面不会解析html标签,会把标签显示出来
        my$("dv").innerHTML = "<p>修抗<p>";//页面会解析html标签,不会把标签显示出来
    }
    my$("but").onclick = function(){
        // console.log(my$("dv").innerText);//修抗 爱惜
        console.log(my$("dv").innerHTML);//修抗 <p>爱惜</p>
    }
</script>

自定义属性操作

<!-- 
自定义属性:本身HTML标签没有这个属性,而是自己添加的
作用:为了存储一些数据
自定义属性无法直接通过DOM对象获取(设置)值的,需要借助方法 setAttribute(属性的名字,属性的值):设置自定义属性和值 getAttribute(属性的名字):获取自定义属性的值
--> <ul id="uu"> <!-- score就是自己添加的属性 --> <li>路飞的成绩</li> <li>娜美的成绩</li> <li>索隆的成绩</li> <li>乔巴的成绩</li> <li>山治的成绩</li> </ul> <script> // 要求:点击名字弹出本人的成绩 // 首先获取ul里面的li标签并添加点击事件 var list = document.getElementById("uu").getElementsByTagName("li"); for (var i = 0; i < list.length; i++) { //为标签添加自定义属性和值 list[i].setAttribute("score",(i+1)*10); list[i].onclick = function(){ // alert(this.score);//弹出的都是undefined // 在html中添加的自定义属性,需要使用 getAttribute("自定义属性的名字") 才能获取自定义属性的值 alert(this.getAttribute("score")); } } </script>

移除属性

<!-- removeAttribute:移除元素的属性-->
<p id="xiu">按钮</p>
<script>
    //要求:删除p标签的id属性
    document.getElementsByTagName("p")[0].removeAttribute("id");
</script>

 节点操作

<!-- 
节点关系:
<html>
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <p>内容</p>
        <div>标签</div>
    </body>
</html>
html 的子节点是 head body
head body 的父节点是 html
meta title 是兄弟节点
-->
<div id="dv">
    <p id="p1">p标签</p>
    <span id="sp">span标签</span>
    <s>s标签</s>
</div>
<script>
    var p1 = document.querySelector("#p1");
    var dv = document.querySelector("#dv");
    var sp = document.querySelector("#sp");
    // 获取p标签的父节点(父节点)
    console.log(p1.parentNode);
    // 获取p标签的父元素(父元素)
    console.log(p1.parentElement);
    // 获取div的子节点(子节点)
    console.log(dv.childNodes);//5个字节点(换行也是节点)
    // 获取div的子元素(子元素)
    console.log(dv.children);//3个字元素
    // 获取div的第一个子节点(第一个子节点)
    console.log(dv.firstChild);//是换行 #text
    // 获取div的第一个子元素(第一个子元素)
    console.log(dv.firstElementChild);//获取的是p标签
    // 获取div的最后一个子节点(最后一个子节点)
    console.log(dv.lastChild);//是换行 #text
    // 获取div的最后一个子元素(最后一个子元素)
    console.log(dv.lastElementChild);//获取的是s标签
    // 获取span的前一个兄弟节点(前一个兄弟节点)
    console.log(sp.previousSibling);//是换行 #text
    // 获取span的前一个兄弟元素(前一个兄弟元素)
    console.log(sp.previousElementSibling);//获取的是p标签
    // 获取span的后一个兄弟节点(后一个兄弟节点)
    console.log(sp.nextSibling);//是换行 #text
    // 获取span的后一个兄弟元素(后一个兄弟元素)
    console.log(sp.nextElementSibling);//获取的是s标签
    // 获取div的id属性节点()
    console.log(dv.getAttributeNode("id"));//id='p1'

    // 节点的属性:
    // nodeType 节点的类型(返回数字 1标签 2属性 3文本)
    // nodeName 节点的名字(标签节点-大写的标签名字 属性节点-小写的属性名字 文本节点-#text)
    // nodeValue 节点的值(标签节点-null 属性节点-属性值 文本节点-文本内容)
    //标签
    var p2 = document.querySelector("#p1");
    console.log(p2.nodeType);//1
    console.log(p2.nodeName);//P
    console.log(p2.nodeValue);//null
    // 属性
    var typeP = p2.getAttributeNode("id");
    console.log(typeP.nodeType);//2
    console.log(typeP.nodeName);//id
    console.log(typeP.nodeValue);//p1
</script>

创建元素的几种方式

<script>
    // 将DOM操作id的DOM封装起来
    function my$(id){
        return document.getElementById(id);
    }
</script>
<!-- 
oppendChild(obj);
把新元素追加到子元素后面
 -->
 <input type="button" value="按钮1" id="but1" />
 <div id="dv1"></div>
 <script>
     // 先创建一个元素
     var i = 0;
     my$("but1").onclick = function(){
         i++;
        var butObj = document.createElement("input");
         butObj.type    = "button";
         butObj.value = "按钮"+i;
        my$("dv1").appendChild(butObj);
     }
 </script>

<!-- 
insertBefore(newObj,obj);
把新元素追加到指定子元素前面
 -->
 <input type="button" value="按钮2" id="but2" />
 <div id="dv2"></div>
 <script>
     // 先创建一个元素
     my$("but2").onclick = function(){
         i++;
        var butObj = document.createElement("input");
         butObj.type    = "button";
         butObj.value = "按钮"+i;
        my$("dv2").insertBefore(butObj,my$("dv2").firstElementChild);
     }
 </script>
<!-- 
replaceChild(); 
替换子元素
-->
<input type="button" value="按钮3" id="but3" />
<div id="dv3">
    <p>修抗</p>
</div>
<script>
    document.getElementById("but3").onclick = function(){
        var sObj = document.createElement("s");
        sObj.innerHTML = "xiukang";
        var dv3Obj = document.querySelector("#dv3");
        dv3Obj.replaceChild(sObj,dv3Obj.firstElementChild);
    }
</script>

<!-- 
removeChild(obj);
删除子元素
 -->
 <input type="button" value="按钮4" id="but4" />
<div id="dv4">
    <p>修抗1</p>
    <p>修抗2</p>
    <p>修抗3</p>
</div>
<script>
    my$("but4").onclick = function(){
        while(my$("dv4").firstElementChild){
            my$("dv4").removeChild(my$("dv4").firstElementChild);
        }
    }
</script>

只创建一个元素

<input type="button" value="按钮" id="btn"/>
<div id="dv"></div>
<script>
    // 只创建一个元素
    // 思路:判断有没有该元素,有则删除,无则创建
    var i=0;
    document.getElementById("btn").onclick = function(){
        i++;
        var pObj = document.createElement("p");
        pObj.id = "xiu";
        pObj.innerHTML = "修抗"+i;
        if(document.getElementById("xiu")){
            document.getElementById("dv").removeChild(document.getElementById("xiu"));
        }
        document.getElementById("dv").appendChild(pObj);
    }
</script>

克隆节点

<div>
    <a href="#"><img src="images/timg.jpg" alt=""></a>
</div>
<script>
    /*
    克隆节点
    cloneNode(true)
    参数为布尔类型:true表示连子节点一起克隆
     */ 
    var aObj = document.getElementsByTagName("a")[0].cloneNode(false);
    document.getElementsByTagName("div")[0].appendChild(aObj);
</script>

为元素添加多个重复的事件

<!-- 
addEventListener() 
参数1:事件的类型,没有on
参数2:事件的处理函数
参数3:布尔类型,目前就写false
this指向当前绑定的对象
谷歌,火狐支持,IE8不支持
-->
<!-- 要求:给按钮添加多个点击事件 -->
<input type="button" value="按钮" id="btn1"/>
<script>
    document.getElementById("btn1").addEventListener("click",function(){
        console.log("修抗1");
    },false);
    document.getElementById("btn1").addEventListener("click",function(){
        console.log("修抗2");
    },false);
</script>

<!-- 
attachEvent()
参数1:事件的类型
参数2:事件的处理函数
this指向window对象
谷歌,火狐不支持,IE8支持
 -->
 <!-- 要求:给按钮添加多个点击事件 -->
<input type="button" value="按钮" id="btn2"/>
<script>
    document.getElementById("btn2").attachEvent("onclick",function(){
        console.log("修抗3");
    });
    document.getElementById("btn2").attachEvent("onclick",function(){
        console.log("修抗4");
    });
</script>

<!-- 
因为不同浏览器使用的方法不一样
所以需要设置兼容代码
原理:判断 对象.方法 如果为fasle就不支持该方法 不要小括号(如果有小括号就是该方法的返回值)
 -->
 <script>
     function addEventListener(elem,type,fun){
         if(elem.addEventListener){
             elem.addEventListener(type,fun,false);
         }else if(elem.attachEvent){
             elem.attachEvent("on"+type,fun);
         }else {
             elem["on"+type] = fun;
         }
     }
     addEventListener(document.querySelector("#btn1"),"click",function(){
         alert(2);
     });
 </script>

 解绑事件

<!-- 
方式1:
将事件处理函数设置为null就可以解绑事件了
 -->
<input type="button" value="绑定事件1" id="btn1"/>
<input type="button" value="解除事件1" id="btn2"/>
<script>
document.getElementById("btn1").onclick = function(){
    console.log("绑定事件1");
}
document.getElementById("btn2").onclick = function(){
    document.getElementById("btn1").onclick = null;
}
</script>

<!-- 
方式2:
使用removeEventListener()解除事件
参数1:事件的名字
参数2:处理函数的名字(须是命名函数)
参数3:false
IE8不支持
 -->
<input type="button" value="绑定事件2" id="btn3"/>
<input type="button" value="解除事件2" id="btn4"/>
<script>
function f1(){
    console.log("绑定事件2");
}
document.querySelector("#btn3").addEventListener("click",f1,false);//设置命名函数
document.querySelector("#btn4").onclick = function(){
    document.querySelector("#btn3").removeEventListener("click",f1,false);
}
</script>

<!-- 
方式3:
使用detachEvent()解除事件
参数1:事件的名字
参数2:处理函数的名字(须是命名函数)
只有IE8支持
 -->
<input type="button" value="绑定事件3" id="btn5"/>
<input type="button" value="解除事件3" id="btn6"/>
<script>
function f2(){
    console.log("绑定事件3");
}
document.querySelector("#btn5").attachEvent("onclick",f2);//设置命名函数
document.querySelector("#btn6").onclick = function(){
    document.querySelector("#btn5").detachEvent("onclick",f2);
}
</script>

<!-- 设置解绑函数的兼容代码 -->
<script>
    function removeEventListener(elen,type,funName){
        if(elen.removeEventListener){
            elen.removeEventListener(type,funName,false);
        }else if(elen.retachEvent){
            elen.retachEvent("on"+type,funName);
        }else{
            elen["on"+type] = null;
        }
    }
</script>

事件冒泡

<!-- 
事件冒泡
有多个元素嵌套,并且这些元素都绑定了相同的事件,如果里面的事件触发了.那么外面元素的事件会主动触发
 -->
<div id="dv1" style="width:300px;height:300px;background-color: red">
    <div id="dv2" style="width:200px;height:200px;background-color: blue">
        <div id="dv3" style="width:100px;height:100px;background-color: yellow"></div>
    </div>
</div>
<script>
document.getElementById("dv1").onclick = function(){
    console.log(this.id);
}
document.getElementById("dv2").onclick = function(){
    console.log(this.id);
    //IE谷歌支持,火狐不支持
    window.event.cancelBubble = true;
}
// 事件处理函数参数对象
document.getElementById("dv3").onclick = function(e){
    console.log(this.id);
    //谷歌火狐支持,IE8不支持
    e.stopPropagation();
}
</script>

输入框的提示信息

<div id="dv">
    <input type="text" id="txt" />
</div>
<script>
    function my$(id){
        return document.getElementById(id);
    }
    var keyWord = ["小明你好","小杨你不好","小明你不好啊","苹果吃了","苹果不能吃"];
    //设置输入框的键盘松开事件(onkeyup)
    my$("txt").onkeyup = function(){
        // 创建一个新数组
        var newKeyWord = [];
        // 获取输入框的值
        var text = this.value;
        for(var i=0;i<keyWord.length;i++){
            // 判断是否有该字符并且索引为0
            if(keyWord[i].indexOf(text)==0){
                // 将元素追加到新数组中
                newKeyWord.push(keyWord[i]);
            }
        }
        if(my$("dv1")){
            my$("dv").removeChild(my$("dv1"));
        }
        // 判断新数组的元素是否为0或者文本框的长度为0
        if(newKeyWord.length==0 || this.value.length==0){
            if(my$("dv1")){
                my$("dv").removeChild(my$("dv1"));
            }
            return;
        }
        var divObj = document.createElement("div");
        divObj.style.width = "158px";
        divObj.style.border = "1px solid red";
        divObj.id = "dv1";
        my$("dv").appendChild(divObj);
        for (var i = 0; i < newKeyWord.length; i++) {
            var pObj = document.createElement("p");
            pObj.innerHTML = newKeyWord[i];
            divObj.appendChild(pObj);
        }
    }
</script>

BOM介绍

/*
浏览器中的顶级对象:window
页面中的顶级对象:document
页面中所有内容都是属于浏览器的,页面中的内容也是window的
*/

var num = 10;
console.log(window.num);

function f1(){
    console.log("修抗");
}
window.f1();//方法的本质的函数,函数也是方法

window.document.write("haha");

// 因为页面中的所有内容都是window的,所以window可以省略

alert(window.name);//该属性有点特殊,输出是空白,一般没有的属性输出都是undefined


// 下面两个是一样的,如果window被占用了就可以使用top
console.log(top);
console.log(window);

对话框

// 下面三个方式,尽量在测试的时候用,因为每个浏览器的样式都不同,而且无法改变样式
// 一般用css做出来
window.alert("弹出提示框");
window.prompt("请输入账号");
window.confirm("你确定退出吗");

页面加载事件

window.onload = function(){
    alert("页面加载完毕后才触发的事件,页面中的节点包括外部引入的js文件");
}
// 扩展事件:谷歌不支持,IE8支持
window.onunload = function(){
    alert("页面关闭后才触发的事件");
}
window.onbeforeunload = function(){
    alert("页面关闭前触发的事件");
}

location对象(浏览器地址栏)

// 获取的是#及后面的内容
console.log(window.location.hash);
// 获取的是主机名及端口号
console.log(window.location.host);
// 获取的是主机名
console.log(window.location.hostname);
// 获取的是文件的相对路径
console.log(window.location.pathname);
// 获取的是端口号
console.log(window.port);
// 获取的是协议
console.log(window.location.protocol);
// 获取的是?及后面的内容
console.log(window.location.search);

// 设置浏览器地址并跳转
window.location.href = "https://www.baidu.com";//属性
window.location.assign("https://www.baidu.com");//方法
window.location.replace("https://www.baidu.com");//没有历史记录(不能后退)

// 重新加载页面
window.location.reload();

history对象(浏览器前进后退功能)

window.history.forward();//前进
window.history.back();//后退

navigator对象(获取浏览器和操作系统的类型)

//获取当前浏览器的类型
console.log(navigator.userAgent);
//获取当前操作系统的类型
console.log(navigator.platform);

定时器

/*
定时器:setInterval()
参数1:函数
参数2:时间(毫米)
返回值:定时器的id
执行过程:每隔一段时间就执行一次函数
 */
var timeId = setInterval(function(){
    console.log("哈哈");
},1000);
/*
停止定时器:clearInterval()
参数:定时器的id
 */
clearInterval(timeId);

/*
一次性定时器:setTimeout
参数1:函数
参数2:时间(毫米)
返回值:定时器的id
执行过程:隔一段时间只执行一次函数
 */ 
var timeId2 = setTimeout(function(){
    console.log("只执行一次");
});
/*
停止一次性定时器:clearTimeout()
参数:定时器的id
虽然说一次性定时器执行一次就不执行了,但内存中还是有该定时器存在占空间的
 */
claerTimeout(timeId2);

定时器案例1(随机图片位置,动画效果)

<input type="button" id="but1" value="执行"/>
<input type="button" id="but2" value="暂停"/><br/>
<img src="images/timg.jpg" alt="" width="200">
<script>
    var timeId;
    document.getElementById("but1").onclick = function(){
         timeId = setInterval(function(){
            var x = Math.random()*100+1;
            var y = Math.random()*100+1;
            document.querySelectorAll("img")[0].style.marginTop = x+"px";
            document.querySelectorAll("img")[0].style.marginLeft = y+"px";
        },100);
    }
    document.getElementById("but2").onclick = function(){
        clearInterval(timeId);
    }
</script>

定时器案例2(等待多少秒点击按钮)

<input type="button" value="重新获取验证码5秒" id="but" disabled/>
<script>
    var time = 5;
    var timeId = setInterval(function(){
        time--;
        if(time>0){
            document.getElementById("but").value ="重新获取验证码"+time+"";
        }else {
            document.getElementById("but").value ="重新获取验证码";
            document.getElementById("but").disabled = false;
            clearInterval(timeId);
        }
        
    },1000);
</script>

定时器案例3(设置图片渐变透明化,动画效果)

<img src="images/timg.jpg" alt="" width="300" id="im"/>
<input type="button" value="渐变" id="but">
<script>
document.getElementById("but").onclick = function(){
    var opacity = 10;
    
    var timeId = setInterval(function(){
        opacity--;
        if(opacity==0){
            clearInterval(timeId);
        }
        document.getElementById("im").style.opacity = opacity/10;
    },200);
    
}
</script>

定时器案例4(设置div宽度,动画效果)

<input type="button" value="按钮" id="but">
<div id="dv" style="width:100px;height:100px;background-color:red"></div>
<script>
document.getElementById("but").onclick = function(){
    /*
    为了防止定时器还没有执行完成就又重新打开定时器
    所以需要提前清除定时器
    需要在定时器返回值前面添加一个对象
     */ 
    clearInterval(document.getElementById("but").timeId);
    var width = 100;
    document.getElementById("but").timeId = setInterval(function(){
        width+=10;
        if(width == 400){
            clearInterval(document.getElementById("but").timeId);
        }
        document.getElementById("dv").style.width = width+"px";
    },100);
    
}
</script>

定时器案例4(设置div位置,动画效果)

<input type="button" value="移动到200px" id="but">
<input type="button" value="移动到400px" id="but2">
<div id="dv" style="width:100px;height:100px;background-color:red;position:relative"></div>
<script>
function animate(elem,target){
    //获取目标当前位置
    var left = elem.offsetLeft;
    var timeId = setInterval(function(){
        // 设置每次移动的步数
        var stop = 20;
        var stop = target>left?stop:-stop;
        // 设置每次移动后的位置
        left+=stop;
        if(Math.abs(target-left)>Math.abs(stop)){
            elem.style.left = left+"px";
        }else{
            clearInterval(timeId);
            elem.style.left = target+"px";
        }
    },100);
}
document.getElementById("but").onclick = function(){
    animate(document.getElementById("dv"),200);
}
document.getElementById("but2").onclick = function(){
    animate(document.getElementById("dv"),400);
}
</script>

js三大系列

<style>
    body {
        margin: 0;
        padding: 0;
    }
    #dv {
        position: absolute;
        width: 100px;
        height: 100px;
        border: 1px solid red;
        padding: 1px;
        margin: 1px;
        left: 1px;
        top: 1px;
        overflow: auto;
    }
</style>
<div id="dv">地铁太挤工作不易,你可曾见过火车上肩扛手提,许多我们叫爸的人拖着比自己都高的行李奔赴生计压力太大生活艰辛.</div>
<script>
    // offsetWidth获取对象的宽度 offsetWidth = border + padding + width
    // offsetHeight获取对象的高度 offsetHeight = border + padding + height
    var dv = document.getElementById("dv");
    console.log(dv.offsetWidth);//104 = width + border(左右边框) + padding(左右内边距)
    console.log(dv.offsetHeight);//104 = height + border(上下边框) + padding(上下内边距) 

    // offsetLeft获取对象距离左边的距离
    // offsetTop获取对象距离顶边的距离
    console.log(dv.offsetTop);//1 = margin-top + 距离上body的距离 未脱离文档流
    console.log(dv.offsetLeft);//4 = margin-left + 距离右body的距离 未脱离文档流
    console.log(dv.offsetTop);//2 = margin-top + top 脱离文档流
    console.log(dv.offsetLeft);//5 = margin-left + left 脱离文档流

    // clientWidth获取网页可视区域的宽度
    console.log(document.body.clientWidth);

    // 滚动事件
    dv.onscroll = function(){
        // 获取垂直滚动后的距离
        console.log(dv.scrollTop);
        // 获取水平滚动后的距离
        console.log(dv.scrollLeft);
        // 获取实际内容的宽度
        console.log(dv.scrollWidth);
        // 获取实际内容的高度
        console.log(dv.scrollHeight);
    }
</script>

通过document获取元素

//获取的是body标签,如果在外部引用的js中获取的是null
console.log(document.body);
// 获取的是title标签中的文本
console.log(document.title);
// 获取html标签
console.log(document.documentElement);

 轮播图

<style>
    *{
        margin: 0;
        padding: 0;
    }
    #lbt {
        width: 500px;
        height: 280px;
        position: relative;
        margin: 0 auto;
        overflow: hidden;

    }
    #photo {
        width: 500px;
        height: 280px;
    }
    #photo ul {
        position: absolute;
        width: 2000px;
    }
    #photo li {
        list-style: none;
        float: left;
    }
    #focus {
        width: 500px;
        position: absolute;
        top: 140px;
        color: #fff;
        text-align: center;
        line-height: 25px;
        display: none;
    }
    #focus span {
        display: block;
        width: 40px;
        height: 25px;
        background-color: rgb(0,0,0,0.2);
    }
    #focus span:nth-child(1){
        float: left;
    }
    #focus span:nth-child(2){
        float: right;
    }
    #serial {
        position: absolute;
        right: 10px;
        bottom: 10px;
    }
    s {
        display: block;
        width: 15px;
        height: 15px;
        background-color: red;
        float: left;
        margin: 0 10px;
        border-radius: 50%;
    }
    .s{
        background-color: blue;
    }
</style>
<div id="lbt">
    <!-- 轮播图的图片 -->
    <div id="photo">
        <ul>
            <li><img src="images/1.jpg" alt="" width="500"></li>
            <li><img src="images/2.jpg" alt="" width="500"></li>
            <li><img src="images/3.jpg" alt="" width="500"></li>
            <li><img src="images/4.jpg" alt="" width="500"></li>
        </ul>
    </div>
    <!-- 轮播图的序列号 -->
    <div id="serial">
    </div>
    <!-- 轮播图的左右焦点 -->
    <div id="focus">
        <span>&lt;</span><span>&gt;</span> 
    </div>
</div>
<script>
    //将指定目标移动多少距离
    function animate(elem,target){
        //获取目标当前位置
        var left = elem.offsetLeft;
        var timeId = setInterval(function(){
            // 设置每次移动的步数
            var stop = 20;
            var stop = target>left?stop:-stop;
            // 设置每次移动后的位置
            left+=stop;
            if(Math.abs(target-left)>Math.abs(stop)){
                elem.style.left = left+"px";
            }else{
                clearInterval(timeId);
                elem.style.left = target+"px";
            }
        },10);
    }
    var lbt = document.getElementById("lbt");
    // 获取整个轮播图的div
    var photo = lbt.children[0];
    // 获取相框
    var ulObj = photo.children[0];
    // 获取序列号
    var serial = lbt.children[1];
    var focus = lbt.children[2];
    // 获取左焦点
    var leftSpan = focus.children[0];
    // 获取右焦点
    var rightSpan = focus.children[1];
    // 定义一个全局变量
    var xiu = 0;
    // 设置序列号
    for (var i = 0; i < ulObj.children.length; i++) {
        // 创建s标签
        var sObj = document.createElement("s");
        // 添加自定义属性
        sObj.setAttribute("index",i);
        // 为序列号添加鼠标进入时间
        sObj.onmouseover = function(){
            // 先删除所有s标签的样式
            for (var i = 0; i < serial.children.length; i++) {
                serial.children[i].removeAttribute("class")
            }
            // 然后在当前s标签中添加样式
            this.className = "s";
            xiu = this.getAttribute("index");
            // 将相框移动位置
            animate(ulObj,-xiu*500);
        }
        // 将创建好的s标签添加到序列号中
        serial.appendChild(sObj);
    }
    //设置默认第一个序列号的样式
    serial.children[0].className = "s";
    // 因为做无缝效果,克隆第一张图片并添加到图片最后
    ulObj.appendChild(ulObj.children[0].cloneNode(true)) ;
    // 设置相框的宽度为所有图片宽度总和
    ulObj.style.width = ulObj.children.length*500+"px";
    //设置显示或者隐藏左右焦点
    photo.onmouseover = function(){
        focus.style.display = "block";
    }
    photo.onmouseout = function(){
        focus.style.display = "none";
    }
    focus.onmouseover = function(){
        focus.style.display = "block";
    }
    focus.onmouseout = function(){
        focus.style.display = "none";
    }
    // 为右焦点添加点击事件
    rightSpan.onclick = rightOver;
    // 右焦点的点击事件
    function rightOver(){
        // 判断是不是最后一张图片
        if(xiu==ulObj.children.length-1){
            xiu = 0;
            // 因为第一张图片和最后一张图片是一样的
            // 所有如果是最后一张图就把图片设置为第一张图片
            // 用户可以最后一张图是第一张图片的错觉
            ulObj.style.left = 0;
            serial.children[0].className = "s";
        }

        xiu++;
        animate(ulObj,-xiu*500);
        //删除所有序列号样式
        for (var i = 0; i < serial.children.length; i++) {
            serial.children[i].removeAttribute("class")
        }
        // 如果是最后一张图片,那么就把第一个序列号设置样式,其他的默认
        if(xiu==ulObj.children.length-1){
            serial.children[0].className = "s";
        }else {
            serial.children[xiu].className = "s";
        }
    }
    // 为左焦点添加点击事件
    leftSpan.onclick = function(){
    if(xiu==0){
        xiu = ulObj.children.length-1;
        ulObj.style.left =-xiu*500+"px";
    }
    xiu--;
    for (var i = 0; i < serial.children.length; i++) {
            serial.children[i].removeAttribute("class")
    }
    serial.children[xiu].className = "s";
    animate(ulObj,-(xiu)*500);
    }
    // 设置自动轮播图
    // 原理就是重复点右焦点现实轮播图
    setInterval(rightOver,1000);
</script>

 正则表达式

// 中括号
// [0-9]匹配任何从0到9的十进制数
// [a-z]匹配任何小写从a到z的字符
// [A-Z]匹配任何大小从A到Z的字符
// [A-Za-z]匹配任何大写A到小写z的字符

// 量词
// p+。匹配任何至少包含一个字符p的字符串
// p*。匹配任何包含零个或多个字符p的字符串
// p?。匹配任何包含零个或一个字符p的字符串
// p{2}。匹配任何包含两个连续p的字符串
// p{2,3}。匹配任何包含两个或三个连续p的字符串
// p{2,}。匹配任何包含两个或以上p的字符串
// p$。匹配任何以p结尾的字符串
// ^p。匹配任何以p开头的字符串
// [^0-9]。匹配任何不包含0到9的十进制数
// p.p。匹配任何包含p和p之间的字符串
// ^.{2}$。匹配任何只包含两个字符的字符串
// <b>(.*)</b>。匹配任何被<b></b>包围的字符串
// p(hp)*。匹配任何包含一个p,p后面是hp的字符串

// 预定义字符范围(字符类)
// [:digit:]数字[0~9]
// [:lower:]小写字母[a~z]
// [:upper:]大写字母[A~Z]
// [:alpha:]大小写字母[A~Za~z]
// [:alnum:]大小写字母以及数字[A~Za~z0~9]
// [:xdigit:]十六进制字符[A~Fa~f0~9]
// [:graph:]33~126范围的可打印ASCII字符
// [:cntrl:]控制字符,如制表符、退格符或反斜杠
// [:space:]空白字符:空格、水平制表符、垂直制表符、换行、换页或换行
// [:punct:]标点符号

// 修饰符
// i不区分大小写
// g查找所有出现
// m将字符串视为多行
// s将字符串视为一行
// x忽略正则表达式中的空格和注释

// 元字符
// \A 只匹配字符串开头
// \b 匹配单词边界
// \B 匹配除单词边界之外的任何字符
// \d 匹配数字字符
// \D 匹配非数字字符
// \s 匹配空白字符
// \S 匹配非空白字符
// [] 包围一个字符类
// () 包围一个字符分组或定义一个反引用
// $ 匹配行尾
// ^ 匹配行首
// . 匹配除换行之外的任何字符
// \ 引出下一个元字符
// \w 匹配任何只包含数字字母和下划线的字符串
// \W 忽略下划线、数字和字母


// 创建正则表达式对象
var reg = new RegExp(/^[a-z]/);
// 调用方法验证字符串是否匹配,返回布尔值
var flag = reg.test("sfsdew");
console.log(flag);
/*
var reg = /^[a-z]/;
var flag = reg.test("sfsdew");
console.log(flag);

var flag = /^[a-z]/.test("sfsdew");
console.log(flag);
 */

// 正则表达式的其他方法:

var str1 = "费12劲34即56放78解90分";
// 要求:将字符串中的数字提取出来放在数组中
var arr1 = str1.match(/[0-9]+/g);
console.log(arr1);//[12,34,56,78,90]

var str2 = "2018-08-09";
// 要求:将字符串中的年月日分别提取出来
var arr2 = str2.match(/(\d+)[-](\d+)[-](\d+)/);
console.log(RegExp.$1);//2018
console.log(RegExp.$2);//08
console.log(RegExp.$3);//09

var str3 = "修抗你好哟,真的好哟";
// 要求:将字符串中的"好"替换成"不好"
var arr3 = str3.replace(/好/g,"不好");
console.log(arr3);//修抗你不好哟,真的不好哟

var str4 = " 修 抗 ";
// 要求:删除字符串中的所有空格
var arr4 = str4.replace(/\s+/g,"");
console.log(arr4);

var str5 = "HHhhsabcdhhH";
// 要求:将字符串中的大小写"h"替换成"A"
var arr5 = str5.replace(/[h]/gi,"A");
console.log(arr5);//AAAAsabcdAAA

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

   

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

posted @ 2018-09-05 12:29  黄强小菜鸟  阅读(627)  评论(0编辑  收藏  举报