JavaScript入门

Posted 黄强

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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>

offset系列

<style>
    #dv1{
        width: 200px;
        height: 200px;
        background-color: red;
    }

    #dv2{
        width: 100px;
        height: 100px;
        background-color: blue;
    }
</style>
<div id="dv1" style="width:100px">
    <div id="dv2"></div>
</div>
<input type="button" value="效果" id="btn">
<script>
    var dv1 = document.getElementById("dv1");
    var dv2 = document.getElementById("dv2");
    document.getElementById("btn").onclick = function(){
        /*
        在style标签中设置的样式是获取不到的
        只能获取style属性中设置的样式
        所以这种方式废了
        console.log(dv1.style.width);
        console.log(dv1.style.height);
         */

        /*
        以后获取元素的宽和高,应该使用offset系列来获取
        offsetWidth:获取元素的宽
        offsetHeight:获取元素的高
        offsetTop:获取元素距离上边位置的值
        offsetLeft:获取元素距离左边位置的值
        
        注意事项:
        如果没有脱离文档流,那么:
        offsetLeft = 父级元素margin + 父级元素padding + 父级元素的border + 自己的margin
        如果脱离文档流,那么:
        offsetLeft = 自己的Left + 自己的margin
        offsetTop与offsetLeft是相同的一个道理
         */
        console.log(dv2.offsetWidth);//100
        console.log(dv2.offsetHeight);//100
    }
</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 匹配除单词边界之外的任何字符
// 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










以上是关于JavaScript入门的主要内容,如果未能解决你的问题,请参考以下文章

推荐net开发cad入门阅读代码片段

30秒就能看懂的JavaScript 代码片段

常用Javascript代码片段集锦

Javascript JSON 的问题

48个值得掌握的JavaScript代码片段(上)

如何将此 JavaScript 代码片段翻译成 Parenscript?