javascript ---- 超哥

文章目录

视频
资料

🍀基本语法

入门


helloworld

<!--JS代码需要编写到script标签中-->
<script type="text/javascript">
	
	/*
	 * 控制浏览器弹出一个警告框
	 * alert("哥,你真帅啊!!");
	 */
	
	/*
	 * 让计算机在页面中输出一个内容
	 * document.write()可以向body中输出一个内容
	 * document.write("看我出不出来~~~");
	 */
	
	/*
	 * 向控制台输出一个内容
	 * console.log()的作用是向控制台输出一个内容
	 * console.log("你猜我在哪出来呢?");
	 */
	
	alert("哥,你真帅啊!!");
	document.write("看我出不出来~~~");
	
	console.log("你猜我在哪出来呢?");
</script>

js代码是从上到下依次执行的
严格区分大小写


js编写位置

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		
		<!--
			可以将js代码编写到外部js文件中,然后通过script标签引入
			写到外部文件中可以在不同的页面中同时引用,也可以利用到浏览器的缓存机制
			推荐使用的方式
		-->
		<!--
			script标签一旦用于引入外部文件了,就不能在编写代码了,即使编写了浏览器也会忽略
			如果需要则可以在创建一个新的script标签用于编写内部代码
		-->
		<script type="text/javascript" src="js/script.js"></script>
		<script type="text/javascript">
			alert("我是内部的JS代码");
		</script>
		
		<!--
			可以将js代码编写到script标签	
		<script type="text/javascript">
			
			alert("我是script标签中的代码!!");
			
		</script>
		-->
	</head>
	<body>
		
		<!--
			可以将js代码编写到标签的onclick属性中
			当我们点击按钮时,js代码才会执行
			
			虽然可以写在标签的属性中,但是他们属于结构与行为耦合,不方便维护,不推荐使用
		-->
		<button onclick="alert('讨厌,你点我干嘛~~');">点我一下</button>
		
		<!--
			可以将js代码写在超链接的href属性中,这样当点击超链接时,会执行js代码
		-->
		<a href="javascript:alert('让你点你就点!!');">你也点我一下</a>
		<a href="javascript:;">你也点我一下</a>
		
	</body>
</html>

基本语法


注释

– 单行注释://注释内容
– 多行注释:/注释内容/

  1. JS中严格区分大小写
  2. JS中每一条语句以分号(;)结尾
    如果不写分号,浏览器会自动添加,但是会消耗一些系统资源
    而且有些时候,浏览器会加错分号,所以在开发中分号必须写
  3. JS中会忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化

字面量 & 变量 (概念)

  • 字面量
    比如 :1 2 3 4 5
    字面量都是可以直接使用,但是我们一般都不会直接使用字面量

  • 变量 : 变量可以用来保存字面量,而且变量的值是可以任意改变的
    开发中都是通过变量去保存一个字面量,而很少直接使用字面量
    可以通过变量对字面量进行描述

    • 变量的声明:
      – 使用var关键字声明一个变量。
      var a;

    • 变量的赋值:
      – 使用=为变量赋值。
      a=123;

    • 声明和赋值同时进行:
      – var a = 123;

    //使用,运算符同时声明多个变量
    //var a , b , c;
    
    //可以同时声明多个变量并赋值
    //var a=1 , b=2 , c=3;
    //alert(b);		
    

标识符

指变量、函数、属性的名字,或函数的参数

命名一个标识符时需要遵守如下的规则:
1.标识符中可以含有字母、数字、_、$
2.标识符不能以数字开头
3.标识符不能是ES中的关键字或保留字
4.标识符一般都采用驼峰命名法


🍃数据类型

数据类型指的就是字面量的类型
在JS中一共有六种数据类型

  1. String 字符串
  2. Number 数值
  3. Boolean 布尔值
  4. Null 空值
  5. Undefined 未定义
  6. Object 对象

其中String Number Boolean Null Undefined属于基本数据类型
而Object属于引用数据类型


String
  • 在JS中字符串需要使用引号引起来
  • 使用双引号或单引号都可以,但是不要混着用
  • 引号不能嵌套,双引号不能放双引号,单引号不能放单引号
  • 在字符串中我们可以使用\作为转义字符,当表示一些特殊符号时可以使用\进行转义
    \" 表示 "
    \' 表示 '
    \n 表示换行
    \t 制表符
    \\ 表示\
var str = 'hello';
str = '我说:"今天天气真不错!"';

str = "我说:\"今天\t天气真不错!\"";

Number

① 在JS中所有的数值都是Number类型,包括整数和浮点数(小数)

//数字123
var a = 123;
//字符串123
var b = "123";

②可以使用一个运算符 typeof来检查一个变量的类型

  • 语法:typeof 变量
  • 检查字符串时,会返回string
  • 检查数值时,会返回numbe
console.log(typeof b); //string

③JS中可以表示的数字的最大值
Number.MAX_VALUE : 1.7976931348623157e+308
Number.MIN_VALUE: 5e-324 大于0的最小值

如果使用Number表示的数字超过了最大值,则会返回一个

  • Infinity 表示正无穷
  • -Infinity 表示负无穷
  • 使用typeof检查Infinity也会返回number
a = -Number.MAX_VALUE * Number.MAX_VALUE;
console.log(typeof a); //number

NaN 是一个特殊的数字,表示Not A Number
使用typeof检查一个NaN也会返回number

④在JS中整数的运算基本可以保证精确

var c = 1865789 + 7654321;

如果使用JS进行浮点运算,可能得到一个不精确的结果
所以千万不要使用JS进行对精确度要求比较高的运算

var c = 0.1 + 0.2;
console.log(c);

Boolean

布尔值只有两个,主要用来做逻辑判断
true:表示真
false:表示假

使用typeof检查一个布尔值时,会返回boolean

var bool = false;
console.log(typeof bool); //boolean

Null

Null(空值)类型的值只有一个,就是null
null这个值专门用来表示一个为空的对象
使用typeof检查一个null值时,会返回object

var a = null;
Undefined

Undefined(未定义)类型的值只有一个,就undefind
声明了未定义

var b
console.log(typeof b);//undefind

🟥强制类型转换

指将一个数据类型强制转换为其他的数据类型
类型转换主要指,将其他的数据类型,转换为
String Number Boolean


xxx–>String
方式一: 调用被转换数据类型的toString()方法
  • 该方法不会影响到原变量,它会将转换的结果返回
  • 但是注意:null和undefined这两个值没有toString()方法,如果调用他们的方法,会报错
var a = 123;

//调用a的toString()方法
//调用xxx的yyy()方法,就是xxx.yyy()
a = a.toString(); //"123"

a = true;
a = a.toString(); //"true"

a = null;
//a = a.toString(); //报错

a = undefined;
//a = a.toString(); //报错
方式二:调用String()函数,并将被转换的数据作为参数传递给函数
  • 使用String()函数做强制类型转换时,对于Number和Boolean实际上就是调用的toString()方法
  • 但是对于null和undefined,就不会调用toString()方法它会
    将 null 直接转换为 “null”
    将 undefined 直接转换为 “undefined”
//Number和Boolean实际上就是调用的toString()方法
a = 123;
//调用String()函数,来将a转换为字符串
a = String(a);

a = null;
a = String(a); // "null"

a = undefined;
a = String(a); // "undefined"
方式三:运用 + 运算符

传送
任何的值和字符串做加法运算***,都会先转换为字符串,然后再和字符串做拼串的操作

var c = 123;
c = c + ""; // number --> string

xxx–>Number
转换方式一:使用Number()函数

字符串 --> 数字

  1. 如果是纯数字的字符串,则直接将其转换为数字
  2. 如果字符串中有非数字的内容,则转换为NaN
  3. 如果字符串是一个空串或者是一个全是空格的字符串,则转换为0

- 布尔 --> 数字

  • true 转成 1
  • false 转成 0

null --> 数字 0

undefined --> 数字 NaN

var a = "123";
a = Number(a); //123

a = false;
a = Number(a); //0

a = null;
a = Number(a); //0

a = undefined;
a = Number(a);//NaN
转换方式二:「这种方式专门用来对付字符串」
  • parseInt() 把一个字符串转换为一个整数
    parseInt()可以将一个字符串中的有效的整数内容去出来,然后转换为Number
  • parseFloat() 把一个字符串转换为一个浮点数
  • 如果对非String使用parseInt()或parseFloat()
    它会先将其转换为String然后在操作
a = "123567a567px";
a = parseInt(a); //123567

a = "123.456.789px";
a = parseFloat(a); //123.456


//非String使用parseInt()
a = true;
a = parseInt(a);// NaN

a = 198.23;
a = parseInt(a);// 198

其他进制数字
可以在parseInt()中传递一个第二个参数,来指定数字的进制
a = parseInt(a,10);

			
//十六进制
a = 0x10;
a = 0xff;
a = 0xCafe;

//八进制数字
a = 070;

//二进制数字
//a = 0b10;

//向"070"这种字符串,有些浏览器会当成8进制解析,有些会当成10进制解析
a = "070";

//可以在parseInt()中传递一个第二个参数,来指定数字的进制
a = parseInt(a,10);

方式三: 通过 - * / 转换

传送到知识点
可以通过为一个值 -0 *1 /1来将其转换为Number
原理和Number()函数一样,使用起来更加简单

a = "12" - 0; 
a = "12" * 1;
a = "12" / 1;

方式四: 一元运算符 +

传送到知识点
可以对一个其他的数据类型使用+,来将其转换为number
它的原理和Number()函数一样

+ 1 // 1

+ "1" // 1
+ "false" //NaN
+ "null" //NaN
 
+ null // 0

+ undefined // NaN

+ false // 0

xxx–>Boolean: 使用Boolean()函数
方法一:使用Boolean()函数

数字 ---> 布尔

  • 除了0和NaN,其余的都是true
    字符串 ---> 布尔
  • 除了空串,其余的都是true

null和undefined都会转换为false

对象也会转换为true

var a = 123; //true
a = -123; //true
a = 0; //false
a = Infinity; //true
a = NaN; //false

//调用Boolean()函数来将a转换为布尔值
a = Boolean(a);

//除了`空串`,其余的都是true
a = "hello" //true
a = " ";    //true
a = "false" //true
a = ""		//false
a = Boolean(a);


a = null; //false
a = Boolean(a);

a = undefined; //false
a = Boolean(a);

方法二:逻辑!运算符

知识电梯

  • 如果对一个值进行两次取反,它不会变化
  • 如果对非布尔值进行元素,则会将其转换为布尔值,然后再取反
    所以我们可以利用该特点,来将一个其他的数据类型转换为布尔值
    可以为一个任意数据类型取两次反,来将其转换为布尔值,
    原理和Boolean()函数一样
var b = 10;
b = !!b; //

!!0 //false
!!12 //true
!!-12 //true
!!NaN //false
!!Infinity

!!"0" //true
!!"false" //true
!!"" //false
!!"   "//true

!!null //false

!!undefined //false

🍃运算符

运算符也叫操作符,通过运算符可以对一个或多个值进行运算,并获取运算结果

  • 比如:typeof就是运算符,可以来获得一个值的类型
    它会将该值的类型以字符串的形式返回
    number string boolean undefined object

算数运算符
  • 当对非Number类型的值进行运算时,会将这些值转换为Number然后再运算(除 + 对字符串外)
  • 任何值做- * /运算时都会自动转换为Number,
    可以通过为一个值 -0 *1 /1来将其转换为Number
    原理和Number()函数一样,使用起来更加简单

+

  • +对值进行加法运算,并将结果返回
  • 对两字符串进行加法运算,则会做拼串,会将两个字符串拼接为一个字符串,并返回
    任何的值和字符串做加法运算,都会先转换为字符串,然后再和字符串做拼串的操作
//number
var a = 123;
result = a + 1; //result = 124, a = 123
result = 456 + 789;//1245

//boolean、null、NaN
result = true + 1;//1 + 1 = 2
result = true + false;//1 + 0 = 1
result = 2 + null; // 2 + 0 = 2
result = 2 + NaN; //2 + 0 =2

//string
result = "你好" + "大帅哥";//你好大帅哥
result = 123 + "1"; //
result = true + "hello";

var c = 123;
c = c + ""; // number --> string
result = 1 + 2 + "3"; //33
result = "1" + 2 + 3; //123

-

  • 可以对两个值进行减法运算,并将结果返回
result = 100 - 5; //95

result = 100 - true;//100 - 1 =99

result = 100 - "1";//100 - 1 = 99
result = 100 - "1a";//100 - NaN = NaN

result = 100 - null;//100 - 0 = 100

result = 100 - undefined;//100 - NaN = NaN

*

result = 2 * 2; //4

result = 2 * "8"; // 2 * 8 = 16

result = 2 * undefined; // 2 * NaN = NaN

result = 2 * null; // 2 * 0 = 0

result = 2 * true; // 2 * 1 = 2

/

result = 4 / 2; //2
result = 3 / 2; //1.5

result = 3 / "1"; //3 / 1 = 3
result = 3 / "1a"; // 3 / NaN = NaN 

result = 3 / true; //3 / 1 = 3
result = 3 / false //3 / 0 = Infinity

result = 3 / null; //3 / 0 = Infinity

result = 3 / undefined; //3 / NaN = NaN 

%
% 取模运算(取余数)

result = 9 % 3; //0
result = 9 % 4; //1
result = 9 % 5; //4

一元运算符

一元运算符,只需要一个操作数
+ 正号
正号不会对数字产生任何影响

- 负号
负号可以对数字进行负号的取反

  • 对于非Number类型的值,它会将先转换为Number,然后在运算
  • 可以对一个其他的数据类型使用+,来将其转换为number,它的原理和Number()函数一样

自增 & 自减

自增 ++

  • 对于一个变量自增以后,原变量的值会立即自增1
  • 后++(a++) 和 前++(++a)
    无论是a++ 还是 ++a,都会立即使原变量的值自增1
    a++的值等于原变量的值(自增前的值)
    ++a的值等于新值 (自增后的值)

自减 --: 同自增

var num = 10;
num = ++num;//11
num = num++;//11

分析num =  ++ num
① num自增运算
局部变量:11		操作数栈:
② 压入操作数栈
局部变量:11		操作数栈:11
③ 赋值操作(将操作数栈的值赋值给局部变量num)
局部变量:11		操作数栈:
num = 11


分析num = num ++ 
num = 11 局部变量
① 将局部变量压入操作数栈
局部变量:11		操作数栈:11
② 局部变量自增
局部变量:12		操作数栈:11
③ 赋值操作(将操作数栈的值赋值给局部变量num)
局部变量:11		操作数栈:
num = 11


var i = 1;
i = i++;
var j = i++;
var k = i + ++i*i++;

分析:
var i = 1;
i = i++;//通过上面知识易得 i = 1

var j = i++;//通过上面知识易得 j = 1,i=2

var k = i + ++i*i++;
1.压栈操作时从左向右,i 的值入栈
i = 22

2. ++i 先自增,后入栈
i = 32 3

3. i++ 先入栈,后自增
i = 32 3 3
  ↓
i = 42 3 3	

4.做运算 先乘
3*3 = 9 
i = 42 9

5.做运算 加操作
2 + 9
i = 411

6. 赋值操作
将操作数栈的值赋给 k 变量
i = 4		栈 
k = 11
j = 1

逻辑运算符

JS中为我们提供了三种逻辑运算符
! 非

  • 所谓非运算就是值对一个布尔值进行取反操作,true变false,false变true
  • 如果对一个值进行两次取反,它不会变化
  • 如果对非布尔值进行元素,则会将其转换为布尔值,然后再取反
    所以我们可以利用该特点,来将一个其他的数据类型转换为布尔值
    可以为一个任意数据类型取两次反,来将其转换为布尔值,
    原理和Boolean()函数一样
var a = false;
a = !a; // true

var b = 10;
b = !!b; //

!!0 //false
!!12 //true
!!-12 //true
!!NaN //false
!!Infinity

!!"0" //true
!!"false" //true
!!"" //false
!!"   "//true

!!null //false

!!undefined //false

&& 与

  • 两个值中有false就false,只有两个值都为true,才true
  • JS中的“与”属于短路与,如果第一个false,则不会看第二个值

|| 或

  • 两个值中只要有true,就true如果两个值都为false,才false
  • JS中的“或”属于短路或,如果第一个true,则不会检查第二个值

&& || 非布尔值的情况
对于非布尔值进行与或运算时,会先将其转换为布尔值,然后再运算,并且返回原值

与运算

  • 第一个值为true,则必然返回第二个值
  • 第一个值为false,则直接返回第一个值

或运算

  • 第一个值为true,则直接返回第一个值
  • 第一个值为false,则返回第二个值
1 && 2; //2
0 && 1; //0
//同理
NaN && 0; //NaN
0 && NaN; //0
//同理
"aaa" && 666 //666
"aaa" && "bbb" //"bbb"
"" && 666 //""

2 || 1 //2
2 || NaN; //2
2 || 0; //2
NaN || 1; //1
NaN || 0; //0

-1 || "你好";  // -1
"" || "hello"; //"hello"

赋值运算符
  =
  	可以将符号右侧的值赋值给符号左侧的变量
  += 
  	a += 5 等价于 a = a + 5
  -=
  	a -= 5 等价于 a = a - 5
  *=
  	a *= 5 等价于 a = a * 5
  /=
  	a /= 5 等价于 a = a / 5
  %=
  	a %= 5 等价于 a = a % 5

关系运算符

比较两个值之间的大小关系,关系成立返回true,不成立返回false
> 大于号
>= 大于等于
< 小于号
<= 小于等于

非数值的情况

  • 非数值比较时,会将其转换为数字再比较
  • 符号两侧的值都是字符串时,不会将其转换为数字进行比较
    而会分别比较字符串中字符的Unicode编码

相等运算符

==

  • 当使用==来比较两个值时,类型不同,则会自动进行类型转换,将其转换为相同的类型,然后在比较
  • 转换的类型不一定,大部分情况转员number
  • undefined 衍生自 null,所以这两个值做相等判断时,会返回true
  • NaN不和任何值相等,包括他本身
  • 通过isNaN()函数来判断一个值是否是NaN
1 == 1; //true
1 == "1"; //true (string --> number)

true == "1" //true (string --> number ,boolean --> number)
true == "hello" //false (string --> number ,boolean --> number)

null == 0 //false

undefined == null //true

NaN == NaN //false

//判断b的值是否是NaN
var b = NaN;
isNaN(b)

!=
同上

===
判断两个值是否全等,它和相等类似,不同的是它不会做自动的类型转换
!==


条件运算符

条件表达式?语句1:语句2;

a > b ? alert("a大"):alert("b大");

代码块

JS中{} 只有分组作用没有作用域作用


流程控制

1.条件判断语句
2.条件分支语句
3.循环语句

if语句

if(a > 10 && a <= 20){
	alert("a大于10,并且 a小于等于20");
}	
if(age > 17 && age <= 30){
	alert("你已经成年了");
}else if(age > 30 && age <= 60){
	alert("你已经中年了");
}else if(age > 60 && age <= 80){
	alert("你已经退休了");
}else{
	alert("你岁数挺大的了~~");
}

switch语句

switch(num){
	case 1:
		console.log("壹");
		//使用break可以来退出switch语句
		break;
	case 2:
		console.log("贰");
		break;
	case 3:
		console.log("叁");
		break;
	default:
		console.log("非法数字~~");
		break;
}

while循环

while(true){
	alert(n++);
	
	//判断n是否是10
	if(n == 10){
		//退出循环
		break;
	}
}

do while

do{
	document.write(i++ +"<br />");
}while(i <= 10);

for

for(var i = 0 ; i < 10 ; i++ ){
	alert(i);
}

break

outer:
for(var i=0 ; i<5 ; i++){
	console.log("@外层循环"+i)
	for(var j=0 ; j<5; j++){
		break outer;
		console.log("内层循环:"+j);
	}
}

continue

outer:
for(var i=0 ; i<5 ; i++){
	for(var j=0 ; j<5 ; j++){
		continue;
		console.log("-->"+j);	
	}
	console.log("@--->"+i);
}

常用方法

console.time("test");
console.timeEnd("test");
Math.sqrt(i)

🍀面向对象

🍃对象

对象的分类:

  1. 内建对象 (类似jdk中的类)
    由ES标准中定义的对象,在任何的ES的实现中都可以使用
    比如:Math String Number Boolean Function Object…

  2. 宿主对象(浏览器对象)
    由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
    比如 BOM DOM

  3. 自定义对象
    由开发人员自己创建的对象


创建对象

  • 对象的属性可以是任何数据类型,也可以是一个函数
  • 当函数是一个对象的属性:称该函数时该对象的方法
方式一:new Object()

使用new关键字调用的函数,是构造函数constructor
构造函数是专门用来创建对象的函数
使用typeof检查一个对象时,会返回object

var obj = new Object();
//向obj中添加一个name属性
obj.name = "孙悟空";
//向obj中添加一个gender属性
obj.gender = "男";
//向obj中添加一个age属性
obj.age = 18;
//读取对象中的属性
obj.name = "tom";
//修改对象的属性值
obj.name = "tom";
//删除对象的属性
delete obj.name;
方式二:`字面量形式

对象字面量的属性名可以加引号也可以不加,建议不加,
如果要使用一些特殊的名字,则必须加引号

var obj = {};
obj.name = "孙悟空";


var obj2 = {			
	name:"猪八戒",
	age:13,
	gender:"男",
	test:{name:"沙僧"}
};

🍃函数(function)

  • 函数也是一个对象
  • 函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码)
  • 函数中可以保存一些代码在需要的时候调用
  • 使用typeof检查一个函数对象时,会返回function
var fun = new Function("console.log('Hello 这是我的第一个函数');");

我们在实际开发中很少使用构造函数来创建一个函数对象

使用函数声明创建对象

function fun2(){
	console.log("这是我的第二个函数~~~");
	alert("哈哈哈哈哈");
	document.write("~~~~(>_<)~~~~");
}

函数表达式声明

var fun3 = function(){
	console.log("我是匿名函数中封装的代码");
};

形参声明,调用

  • 调用函数时解析器不会检查实参的类型
  • 多余实参不会被赋值,如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined
function sum(a,b){
	console.log("a = "+a);
	console.log("b = "+b);
	console.log(a+b);
}

sum(1,2);

实参可以是一个对象,也可以是一个函数

function fun(a){
	console.log("a = "+a);
	//a(obj);
}
fun(function(){alert("hello")});

返回值

  • return后的值将会会作为函数的执行结果返回,可以定义一个变量,来接收该结果
  • 如果return语句后不跟任何值就相当于返回一个undefined
  • 如果函数中不写return,则也会返回undefined
  • return后可以跟任意类型的值,也可以是一个对象,也可以是一个函数
  • 变量result的值就是函数的执行结果
function sum(a , b , c){
	//alert(a + b +c);
	var d = a + b + c;
	return d;				
}

var result = sum(4,7,8);
function fun2(){
	//返回一个对象
	return {name:"沙和尚"};
}

function fun3(){
	//在函数内部再声明一个函数
	function fun4(){
		alert("我是fun4");
	}
	//将fun4函数对象作为返回值返回
	return fun4;
}

fun3()();

立即执行函数

  • 函数定义完,立即被调用,这种函数叫做立即执行函数
  • 立即执行函数往往只会执行一次
(function(){
	alert("我是一个匿名函数~~~");
})();

对象属性

  • 可以是任何数据类型,也可以是函数
  • 当函数时对象属性,称该函数时对象的方法
var obj2 = {
	
	name:"猪八戒",
	age:18,
	sayName:function(){
		console.log(obj2.name);
	}
};

obj2.sayName();

枚举对象中的属性
for…in语句 对象中有几个属性,循环体就会执行几次
每次执行时,会将对象中的一个属性的名字赋值给变量

var obj = {
	name:"孙悟空",
	age:18,
	gender:"男",
	address:"花果山"
};

for(var n in obj){
	console.log("属性名:"+n);
	//当对象的属性是变量时,使用[]调用
	console.log("属性值:"+obj[n]);
}

🍃作用域

全局作用域

  • 直接编写在script标签中的JS代码,都在全局作用域

  • 全局作用域在页面打开时创建,在页面关闭时销毁

  • 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用

  • 在全局作用域中:
    创建的变量都会作为window对象的属性保存
    创建的函数都会作为window对象的方法保存

var a = 10;
var b = 20;
var c = "hello";
console.log(window.c);


function fun(){
	console.log("我是fun函数");
}
window.fun();

变量的声明提前

使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值),但是如果声明变量时不使用var关键字,则变量不会被声明提前

console.log("a = "+a);//undefined
var a = 123;

console.log("a = "+a);//报错
a = 123;

函数的声明提前

使用函数声明形式创建的函数 function 函数(){}
它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数
使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用

fun();
//函数声明,会被提前创建
function fun(){
	console.log("我是一个fun函数");
}
//函数表达式,不会被提前创建
var fun2 = function(){
	console.log("我是fun2函数");
};

fun2();

函数作用域

  • 调用函数时 创建函数作用域,函数执行完毕以后,函数作用域销毁
  • 每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立
  • 函数作用域中可以访问全局作用域的变量,在全局作用域中无法访问到函数作用域的变量
  • 先找自身作用域,有就用,没有则向上找,直到找到全局作用域,全局中依然没有,则报错ReferenceError
  • 在函数中要访问全局变量可以使用window对象
//创建一个变量
var a = 10;

function fun(){
	
	var a = "我是fun函数中的变量a";
	var b = 20;
	
	//console.log("a = "+a);
	
	function fun2(){
		//使用window对象
		console.log("a = "+window.a);
	}
	
	fun2();
	
}
  • 函数作用域也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明,函数声明也会在函数中所有的代码执行之前执行
  • 使用var关键字声明的变量,会在函数中所有的代码执行之前被声明
function fun3(){
	
	fun4();
	
	//console.log(a);
	
	var a = 35;
	
	function fun4(){
		alert("I'm fun4");
	}
}
  • 在函数中,不使用var声明的变量都会成为全局变量
  • 定义形参就相当于在函数作用域中声明了变量

🍃this

  • 解析器在调用函数每次都会向函数内部传递进一个隐含的参数,
    这个隐含的参数就是this,this指向的是一个对象,
    这个对象我们称为函数执行的 上下文对象,
    根据函数的调用方式的不同,this会指向不同的对象
    1、以函数的形式调用时,this永远都是window
    2、以方法的形式调用时,this就是调用方法的那个对象
    3、当以构造函数的形式调用时,this就是新创建的那个对象
    4、使用call和apply调用时,this是指定的那个对象
function fun(){
	//console.log("a = "+a+", b = "+b);
	console.log(this.name);
}
//创建一个name变量
var name = "全局";

//创建一个fun()函数
function fun(){
	console.log(this.name);
}

//创建两个对象
var obj = {
		name:"孙悟空",
		sayName:fun
};

var obj2 = {
		name:"沙和尚",
		sayName:fun
};

//我们希望调用obj.sayName()时可以输出obj的名字
//obj.sayName();

obj.sayName();

工厂方法创建对象

/*
 * 使用工厂方法创建对象
 * 	通过该方法可以大批量的创建对象
 */
function createPerson(name , age ,gender){
	//创建一个新的对象 
	var obj = new Object();
	//向对象中添加属性
	obj.name = name;
	obj.age = age;
	obj.gender = gender;
	obj.sayName = function(){
		alert(this.name);
	};
	//将新的对象返回
	return obj;
}

/*
 * 用来创建狗的对象
 */
function createDog(name , age){
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.sayHello = function(){
		alert("汪汪~~");
	};
	
	return obj;
}

var obj2 = createPerson("猪八戒",28,"男");
var obj3 = createPerson("白骨精",16,"女");
var obj4 = createPerson("蜘蛛精",18,"女");
/*
 * 使用工厂方法创建的对象,使用的构造函数都是Object
 * 	所以创建的对象都是Object这个类型,
 * 	就导致我们无法区分出多种不同类型的对象
 */
//创建一个狗的对象
var dog = createDog("旺财",3);

🍃构造函数

创建一个构造函数,专门用来创建Person对象的

  • 构造函数就是一个普通的函数,创建方式和普通函数没有区别,
  • 不同的是构造函数习惯上首字母大写

构造函数和普通函数的区别就是调用方式的不同

  • 普通函数是直接调用,而构造函数需要使用new关键字来调用

构造函数的执行流程:
1.立刻创建一个新的对象
2.将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象
3.逐行执行函数中的代码
4.将新建的对象作为返回值返回

function Person(name , age , gender){
	this.name = name;
	this.age = age;
	this.gender = gender;
	this.sayName = function(){
		alert(this.name);
	};
}
function Dog(){
	
}

var per = new Person("孙悟空",18,"男");
var per2 = new Person("玉兔精",16,"女");
var per3 = new Person("奔波霸",38,"男");

var dog = new Dog();

在Person构造函数中,为每一个对象都添加了一个sayName方法,
也就是构造函数每执行一次就会创建一个新的sayName方法
导致了构造函数执行一次就会创建一个新的方法,

function Person(name , age , gender){
	this.name = name;
	this.age = age;
	this.gender = gender;
	//向对象中添加一个方法
	//this.sayName = fun;
}
//将sayName方法在全局作用域中定义
//将函数定义在全局作用域,污染了全局作用域的命名空间,而且定义在全局作用域中也很不安全
/*function fun(){
	alert("Hello大家好,我是:"+this.name);
};*/

//向原型中添加sayName方法
Person.prototype.sayName = function(){
	alert("Hello大家好,我是:"+this.name);
};

//创建一个Person的实例
var per = new Person("孙悟空",18,"男");
var per2 = new Person("猪八戒",28,"男");
per.sayName();
per2.sayName();

🍃原型 prototype

  • 我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
    这个属性对应着一个对象,这个对象就是我们所谓的原型对象

  • 如果函数作为普通函数调用prototype没有任何作用

  • 当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,
    指向该构造函数的原型对象,我们可以通过__proto__来访问该属性

function MyClass(){

}
var mc = new MyClass();
var mc2 = new MyClass();

//console.log(MyClass.prototype);
//console.log(mc2.__proto__ == MyClass.prototype); //true
//console.log(mc.__proto__ == MyClass.prototype); //true

在这里插入图片描述

  • 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,
    我们可以将对象中共有的内容,统一设置到原型对象中。
  • 当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,
    如果没有则会去原型对象中寻找,如果找到则直接使用
  • 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
    这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了

  • 使用in检查对象中是否含有某个属性
  • 使用对象的hasOwnProperty()来检查对象自身中是否含有该属性
/*
* 创建一个构造函数
*/
function MyClass(){

}

//向MyClass的原型中添加一个name属性
MyClass.prototype.name = "我是原型中的名字";

var mc = new MyClass();
mc.age = 18;

console.log(mc.name);

//使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
console.log("name" in mc);


console.log(mc.hasOwnProperty("age"));

console.log(mc.hasOwnProperty("hasOwnProperty"));
  • 原型对象也是对象,所以它也有原型
  • 当我们使用一个对象的属性或方法时,会现在自身中寻找,
    自身中如果有,则直接使用
    如果没有则去原型对象中寻找,如果原型对象中有,则使用,
    如果没有则去原型的原型中寻找,直到找到Object对象的原型,
    Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined
console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));

console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));

console.log(mc.__proto__.__proto__.__proto__);//null

console.log(mc.hello);

console.log(mc.__proto__.__proto__.__proto__)

toString

function Person(name , age , gender){
	this.name = name;
	this.age = age;
	this.gender = gender;
}
console.log(per.__proto__.__proto__.hasOwnProperty("toString"));//true

//修改Person原型的toString
Person.prototype.toString = function(){
	return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]";
};

//当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值
//如果我们希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法
//Person[name=孙悟空,age=18,gender=男]
/*per.toString = function(){
	return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]";
};*/

//创建一个Person实例
var per = new Person("孙悟空",18,"男");
var per2 = new Person("猪八戒",28,"男");

垃圾回收

  • 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,
    此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,
  • 在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作
  • 我们需要做的只是要将不再使用的对象设置null即可
var obj = new Object();

//对对象进行各种操作。。。。
obj = null;

🍀内建对象

🍃数组(Array)

  • 数组也是一个对象,它和我们普通对象功能类似,也是用来存储一些值的
  • 不同的是普通对象是使用字符串作为属性名的,而数组是使用数字来作为索引操作元素
  • 索引:从0开始的整数就是索引
  • 数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据

  • 如果读取不存在的索引,他不会报错而是返回undefined
//创建数组对象
var arr = new Array();

/*
 * 向数组中添加元素
 * 语法:数组[索引] = 值
 */
arr[0] = 10;
arr[1] = 33;
arr[2] = 22;
arr[3] = 44;

/*
 * 读取数组中的元素
 * 语法:数组[索引]
 * 	如果读取不存在的索引,他不会报错而是返回undefined
 */
console.log(arr[3]);

Array 属性

在这里插入图片描述

/*
 * 获取数组的长度
 * 可以使用length属性来获取数组的长度(元素的个数)
 * 	语法:数组.length
 * 
 * 对于连续的数组,使用length可以获取到数组的长度(元素的个数)
 * 对于非连续的数组,使用length会获取到数组的最大的索引+1
 * 		尽量不要创建非连续的数组
 */
console.log(arr.length);
console.log(arr);

/*
* 修改length
* 	如果修改的length大于原长度,则多出部分会空出来
*  如果修改的length小于原长度,则多出的元素会被删除
*/
arr.length = 10;

arr.length = 2;


//向数组的最后一个位置添加元素
//语法:数组[数组.length] = 值;
arr[arr.length] = 70;
arr[arr.length] = 80;
arr[arr.length] = 90;

数组字面量

  • 使用字面量来创建数组
  • 使用字面量创建数组时,可以在创建时就指定数组中的元素
  • 数组中的元素可以是任意的数据类型
//使用字面量来创建数组
//语法:[]
var arr = [];


//使用字面量创建数组时,可以在创建时就指定数组中的元素
var arr = [1,2,3,4,5,10];

//使用构造函数创建数组时,也可以同时添加元素,将要添加的元素作文构造函数的参数传递
//元素之间使用,隔开
var arr2 = new Array(10,20,30);

//创建一个长度为10的数组
arr2 = new Array(10);
//数组中的元素可以是任意的数据类型
arr = ["hello",1,true,null,undefined];

//也可以是对象
var obj = {name:"孙悟空"};
arr[arr.length] = obj;
arr = [{name:"孙悟空"},{name:"沙和尚"},{name:"猪八戒"}];

//也可以是一个函数
arr = [function(){alert(1)},function(){alert(2)}];

//数组中也可以放数组,如下这种数组我们称为二维数组
arr = [[1,2,3],[3,4,5],[5,6,7]];

数组方法

方法描述
🍃concat()连接两个或多个数组,并返回已连接数组的副本。
copyWithin()将数组中的数组元素复制到指定位置或从指定位置复制。
entries()返回键/值对数组迭代对象。
every()检查数组中的每个元素是否通过测试。
fill()用静态值填充数组中的元素。
filter()使用数组中通过测试的每个元素创建新数组。
find()返回数组中第一个通过测试的元素的值。
findIndex()返回数组中通过测试的第一个元素的索引。
🍃forEach()为每个数组元素调用函数。
from()从对象创建数组。
includes()检查数组是否包含指定的元素。
indexOf()在数组中搜索元素并返回其位置。
isArray()检查对象是否为数组。
🍃join()将数组的所有元素连接成一个字符串。
keys()返回 Array Iteration 对象,包含原始数组的键.
lastIndexOf()在数组中搜索元素,从末尾开始,并返回其位置。
map()使用为每个数组元素调用函数的结果创建新数组。
🍃pop() | shift()删除数组的最后一个元素,并返回元素
🍃push() | unshift()将新元素添加到数组的末尾,并返回新的长度
reduce()将数组的值减为单个值(从左到右)。
reduceRight()将数组的值减为单个值(从右到左)。
reverse()反转数组中元素的顺序。
🍃shift()删除数组的第一个元素,并返回该元素。
🍃slice()选择数组的一部分,并返回新数组
some()检查数组中的任何元素是否通过测试。
sort()对数组的元素进行排序。
🍃splice()从数组中添加/删除元素。
toString()将数组转换为字符串,并返回结果。
🍃unshift()将新元素添加到数组的开头,并返回新的长度。
valueOf()返回数组的原始值。
遍历数组

for遍历

//创建一个数组
var arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];

for(var i=0 ; i<arr.length ; i++){
	console.log(arr[i]);
}

forEach方法

终止或者跳出forEach()循环,除非抛出异常,所以想执行一个数组是否满足某种条件然后返回某值,可以用一般的for循环实现,或者用Array.every()或者Array.some();
Array.every()用于检测数组所有元素是否全部都符合指定条件
Array.some()用于检测数组中的元素是否有任意一个满足指定条件

语法:array.forEach(callback(currentvalue,index,arr) ,thisValue)
//forEach没有返回值
var arr = [1, 3, 5, 13, 2];
var res = arr.forEach(function(item,index) {
    console.log(`数组第${index+1}个元素是${item}`);
})
console.log(res);//forEach的返回值为undefined,
  • forEach() 方法无法提前结束
var arr = [1, 3, 5, 13, 2];
for (var i = 0; i < arr.length; i++) {
    if (arr[i] == 3) {
        console.log("找到了3,并结束循环");
        break;
    }
    console.log(arr[i]);
}


var arr = [1, 3, 5, 13, 2];
arr.forEach(function(item) {
    if (item == 3) {
        return console.log('找到了3,但未结束遍历');
    }
    console.log(item);
})
  • forEach()会跳过空值
var arr1 = [1, 3, , 13, 2];
var arr2 = [1, 3, , 13, 2];
for (var i = 0; i < arr1.length; i++) {
    arr1[i] = 2;
}
console.log(arr1);
var newarr = [];
arr2.forEach(function(item, index) {
    // item = 2; //修改不了原数组            
    arr2[index] = 2;
})
console.log(arr2);

在这里插入图片描述

  • forEach()的循环次数不受数组长度增长影响
  • forEach适用于只是进行集合或数组遍历,for则在较复杂的循环中效率更高

其他方法

var arr = ["孙悟空","猪八戒","沙和尚"];
var arr2 = ["白骨精","玉兔精","蜘蛛精"];
var arr3 = ["二郎神","太上老君","玉皇大帝"];
/*
 * concat()可以连接两个或多个数组,并将新的数组返回
 * 	- 该方法不会对原数组产生影响
 */			
var result = arr.concat(arr2,arr3,"牛魔王","铁扇公主");


/*
 * join()
 * 	- 该方法可以将数组转换为一个字符串
 * 	- 该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回
 * 	- 在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符
 * 		如果不指定连接符,则默认使用,作为连接符
 */
arr = ["孙悟空","猪八戒","沙和尚","唐僧"];

result = arr.join("@-@");

/*
 * reverse()
 * 	- 该方法用来反转数组(前边的去后边,后边的去前边)
 * 	- 该方法会直接修改原数组
 */

arr.reverse();


/*
 * sort()
 * 	- 可以用来对数组中的元素进行排序
 * 	- 也会影响原数组,默认会按照Unicode编码进行排序
 */
arr.sort();

arr = [5,4,2,1,3,6,8,7];

arr.sort(function(a,b){
	
	//前边的大
	/*if(a > b){
		return -1;
	}else if(a < b){
		return 1;
	}else{
		return 0;
	}*/
	
	//升序排列
	//return a - b;
	
	//降序排列
	return b - a;
	
});

函数对象方法

call()和apply()

function fun(a,b) {
	alert(this);
}

//效果一样
fun.apply();
fun.call();
fun();

在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this

function fun(a,b) {
	alert(this);
}
var obj = {};
//修改this指向的对象
fun.call(obj);
fun.apply(obj);
var obj = {
	name: "obj",
	sayName:function(){
		alert(this.name);
	}
};
obj.sayName.apply(obj2);

call()方法可以将实参在对象之后依次传递
apply()方法需要将实参封装到一个数组中统一传递

function fun(a,b) {
	console.log("a = "+a);
	console.log("b = "+b);
	//alert(this);
}

fun.call(obj,2,3);
fun.apply(obj,[2,3]);

arguments 隐含属性

在调用函数时,浏览器每次都会传递进两个隐含的参数:
1.函数的上下文对象 this
2.封装实参的对象 arguments

  • arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度
  • 在调用函数时,我们所传递的实参都会在arguments中保存
  • arguments.length可以用来获取实参的长度
  • 我们即使不定义形参,也可以通过arguments来使用实参,
    只不过比较麻烦
    arguments[0] 表示第一个实参
    arguments[1] 表示第二个实参 。。。
  • 它里边有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象
function fun(a,b){
	//console.log(arguments instanceof Array);
	//console.log(Array.isArray(arguments));
	//console.log(arguments[1]);
	//console.log(arguments.length);
	console.log(arguments.callee == fun);
}

fun("hello",true);

Date对象

  • 创建一个Date对象
  • 创建一个指定的时间对象
  • 获取当前日期对象是几日
  • 获取当前日期对象是周几
  • 获取当前时间对象的月份
  • 获取当前日期对象的年份
  • 获取当前日期对象的时间戳
  • 利用时间戳来测试代码的执行的性能
//创建一个Date对象
//如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间
var d = new Date();
//创建一个指定的时间对象
//需要在构造函数中传递一个表示时间的字符串作为参数
//日期的格式  月份/日/年 时:分:秒
var d2 = new Date("2/18/2011 11:10:30");
/*
* getDate()
* 	- 获取当前日期对象是几日
*/
var date = d2.getDate();
/*
 * getDay()
 * 	- 获取当前日期对象时周几
 * 	- 会返回一个0-6的值
 * 		0 表示周日
 * 		1表示周一
 * 		。。。
 */
var day = d2.getDay();
/*
 * getMonth()
 * d2 = new Date("12/18/2011 11:10:30");
 * - 获取当前时间对象的月份
 * 	- 会返回一个0-11的值
 * 		0 表示1月
 * 		1 表示2月
 * 		11 表示12月
 */
var month = d2.getMonth();
/*
 * getFullYear()
 * 	- 获取当前日期对象的年份
 */
var year = d2.getFullYear();
/*
 * getTime()
 * 	- 获取当前日期对象的时间戳
 * 	- 时间戳,指的是从格林威治标准时间的1970年1月1日,0时0分0秒
 * 		到当前日期所花费的毫秒数(1秒 = 1000毫秒)
 * 	- 计算机底层在保存时间时使用都是时间戳
 */

var time = d2.getTime();
//利用时间戳来测试代码的执行的性能
//获取当前的时间戳
var start = Date.now();

for(var i=0 ; i<100 ; i++){
	console.log(i);
}

var end = Date.now();


console.log("执行了:"+(end - start)+"毫秒");

Math

  • Math.PI 表示的圆周率
  • abs()可以用来计算一个数的绝对值
  • Math.ceil() 向上取整
  • Math.floor() 向下取整
  • Math.round() 四舍五入取整
  • Math.random() 生成一个0-1之间的随机数
  • max() 、min()
  • Math.pow(x,y) x的y次幂
  • Math.sqrt() 开方运算
/*
 * Math
 * 	- Math和其他的对象不同,它不是一个构造函数,
 * 		它属于一个工具类不用创建对象,它里边封装了数学运算相关的属性和方法
 * 	- 比如
 * 		Math.PI 表示的圆周率
 */

console.log(Math.PI);
/*
 * abs()可以用来计算一个数的绝对值
 */
console.log(Math.abs(-1));
/*
 * Math.ceil()
 * 	- 可以对一个数进行向上取整,小数位只有有值就自动进1
 * Math.floor()
 * 	- 可以对一个数进行向下取整,小数部分会被舍掉
 * Math.round()
 * 	- 可以对一个数进行四舍五入取整
 */
console.log(Math.ceil(1.1));
console.log(Math.floor(1.99));
console.log(Math.round(1.4));
/*
 * Math.random()
 * 	- 可以用来生成一个0-1之间的随机数
 *  - 生成一个0-10的随机数
 * 	- 生成一个0-x之间的随机数
 * 		Math.round(Math.random()*x)
 * 
 * 	- 生成一个1-10
 * 	- 生成一个x-y之间的随机数
 * 		Math.round(Math.random()*(y-x)+x)
 */
for(var i=0 ; i<100 ; i++){
	//console.log(Math.round(Math.random()*10));
	//console.log(Math.round(Math.random()*20));
	
	//console.log(Math.round(Math.random()*9)+1);
	//console.log(Math.round(Math.random()*8)+2);
	
	//生成1-6之间的随机数
	console.log(Math.round(Math.random()*5+1));
}
/*
 * max() 可以获取多个数中的最大值
 * min() 可以获取多个数中的最小值
 */

var max = Math.max(10,45,30,100);
var min = Math.min(10,45,30,100);
//console.log(min);

/*
 * Math.pow(x,y)
 * 	返回x的y次幂
 */

console.log(Math.pow(12,3));

/*
 * Math.sqrt()
 *  用于对一个数进行开方运算
 */
console.log(Math.sqrt(2));

包装类

/*
 * 基本数据类型
 * 	String Number Boolean Null Undefined
 * 引用数据类型
 * 	Object
 * 
 * 在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
 * 	String()
 * 		- 可以将基本数据类型字符串转换为String对象
 * 	Number()
 * 		- 可以将基本数据类型的数字转换为Number对象
 *  Boolean()
 * 		- 可以将基本数据类型的布尔值转换为Boolean对象
 * 	但是注意:我们在实际应用中不会使用基本数据类型的对象,
 * 		如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果
 */

//创建一个Number类型的对象
//num = 3;
var num = new Number(3);
var num2 = new Number(3);
var str = new String("hello");
var str2 = new String("hello");
var bool = new Boolean(true);
var bool2 = true;

//向num中添加一个属性
num.hello = "abcdefg";

//console.log(str === str2);

var b = new Boolean(false);

/*if(b){
	alert("我运行了~~~");
}*/
/*
 * 方法和属性之能添加给对象,不能添加给基本数据类型
 * 	当我们对一些基本数据类型的值去调用属性和方法时,
 * 		浏览器会临时使用包装类将其转换为对象,然后在调用对象的属性和方法
 * 		调用完以后,在将其转换为基本数据类型
 */
var s = 123;

s = s.toString();

s.hello = "你好";

console.log(s.hello);
//console.log(typeof s);

字符串相关方法

  • 在底层字符串是以字符数组的形式保存的
  • length属性 : 可以用来获取字符串的长度
  • charAt() : 返回字符串中指定位置的字符
  • charCodeAt() : 获取指定位置字符的字符编码(Unicode编码)
  • formCharCode() :根据字符编码去获取字符
  • concat()
//创建一个字符串
var str = "Hello Atguigu";

/*
 * 在底层字符串是以字符数组的形式保存的
 * ["H","e","l"]
 */

/*
 * length属性
 * 	- 可以用来获取字符串的长度
 */
//console.log(str.length);
//console.log(str[5]);
/*
* charAt()
* 	- 可以返回字符串中指定位置的字符
* 	- 根据索引获取指定的字符	
*/
str = "中Hello Atguigu";
/*
 * charCodeAt()
 * 	- 获取指定位置字符的字符编码(Unicode编码)
 */

result = str.charCodeAt(0);
/*
 * String.formCharCode()
 * 	- 可以根据字符编码去获取字符
 */
result = String.fromCharCode(0x2692);
/*
 * concat()
 * 	- 可以用来连接两个或多个字符串
 * 	- 作用和+一样
 */
result = str.concat("你好","再见");
/*
 * indexof()
 * 	- 该方法可以检索一个字符串中是否含有指定内容
 * 	- 如果字符串中含有该内容,则会返回其第一次出现的索引
 * 		如果没有找到指定的内容,则返回-1
 * 	- 可以指定一个第二个参数,指定开始查找的位置
 * 
 * lastIndexOf();
 * 	- 该方法的用法和indexOf()一样,
 * 		不同的是indexOf是从前往后找,
 * 		而lastIndexOf是从后往前找
 * 	- 也可以指定开始查找的位置
 */

str = "hello hatguigu";

result = str.indexOf("h",1);

result = str.lastIndexOf("h",5);
/*
 * slice()
 * 	- 可以从字符串中截取指定的内容
 * 	- 不会影响原字符串,而是将截取到内容返回
 * 	- 参数:
 * 		第一个,开始位置的索引(包括开始位置)
 * 		第二个,结束位置的索引(不包括结束位置)
 * 			- 如果省略第二个参数,则会截取到后边所有的
 * 		- 也可以传递一个负数作为参数,负数的话将会从后边计算
 */
str = "abcdefghijk";

result = str.slice(1,4);
result = str.slice(1,-1);
/*
 * substring()
 * 	- 可以用来截取一个字符串,可以slice()类似
 * 	- 参数:
 * 		- 第一个:开始截取位置的索引(包括开始位置)
 * 		- 第二个:结束位置的索引(不包括结束位置)
 * 		- 不同的是这个方法不能接受负值作为参数,
 * 			如果传递了一个负值,则默认使用0
 * 		- 而且他还自动调整参数的位置,如果第二个参数小于第一个,则自动交换
 */

result = str.substring(0,1);
/*
 * substr()
 * 	- 用来截取字符串
 * 	- 参数:
 * 		1.截取开始位置的索引
 * 		2.截取的长度
 */

str = "abcdefg";

result = str.substr(3,2);
/*
 * split()
 * 	- 可以将一个字符串拆分为一个数组
 * 	- 参数:
 * 		-需要一个字符串作为参数,将会根据该字符串去拆分数组
 */
str = "abcbcdefghij";

result = str.split("d");

/*
 * 如果传递一个空串作为参数,则会将每个字符都拆分为数组中的一个元素
 */
result = str.split("");

//console.log(Array.isArray(result));
//console.log(result[0]);
console.log(result);
str = "abcdefg";

/*
 * toUpperCase()
 * 	- 将一个字符串转换为大写并返回
 */
result = str.toUpperCase();

str = "ABCDEFG";

/*
* toLowerCase()
* 	-将一个字符串转换为小写并返回
*/
result = str.toLowerCase();

//console.log(result);

正则表达式

  • 创建正则表达式的对象

正则表达式的方法:

  • test()
/*
	 * 正则表达式
	 * 	- admin@atguigu.com
	 *  - admin@.com   adminatguigu.com
	 *  - 邮件的规则:
	 * 		1.前边可以是xxxx乱七八糟
	 * 		2.跟着一个@
	 * 		3.后边可以是xxxx乱七八糟
	 * 		4..com获取其他的乱七八糟
	 * 
	 * 	- 正则表达式用于定义一些字符串的规则,
	 * 		计算机可以根据正则表达式,来检查一个字符串是否符合规则,
	 * 		获取将字符串中符合规则的内容提取出来
	 */
	
	//创建正则表达式的对象
	/*
	 * 语法:
	 * 	var 变量 = new RegExp("正则表达式","匹配模式");
	 *  使用typeof检查正则对象,会返回object
	 * 	var reg = new RegExp("a"); 这个正则表达式可以来检查一个字符串中是否含有a
	 * 在构造函数中可以传递一个匹配模式作为第二个参数,
	 * 		可以是 
	 * 			i 忽略大小写 
	 * 			g 全局匹配模式
	 */
	var reg = new RegExp("ab","i");
	
	var str = "a";
	
	/*
	 * 正则表达式的方法:
	 * 	test()
	 * 	 - 使用这个方法可以用来检查一个字符串是否符合正则表达式的规则,
	 * 		如果符合则返回true,否则返回false
	 */
	var result = reg.test(str);
	//console.log(result);
	console.log(reg.test("Ac"));
/*
 * 使用字面量来创建正则表达式
 * 	语法:var 变量 = /正则表达式/匹配模式
 * 使用字面量的方式创建更加简单
 * 	使用构造函数创建更加灵活
 * 
 */
//var reg = new RegExp("a","i");

var reg = /a/i;

//console.log(typeof reg);
//console.log(reg.test("abc"));

//创建一个正则表达式,检查一个字符串中是否有a或b
/*
 * 使用 | 表示或者的意思
 */
reg = /a|b|c/;

/*
 * 创建一个正则表达式检查一个字符串中是否有字母
 */
//reg = /a|b|c|d|e|f|g/;

/*
 * []里的内容也是或的关系
 * [ab] == a|b
 * [a-z] 任意小写字母
 * [A-Z] 任意大写字母
 * [A-z] 任意字母
 * [0-9] 任意数字
 */
reg = /[A-z]/;

//检查一个字符串中是否含有 abc 或 adc 或 aec
reg = /a[bde]c/;

/*
 * [^ ] 除了
 */
reg = /[^ab]/;

reg = /[^0-9]/;

console.log(reg.test("12a3456"));

字符串正则

  • split()
  • search()
  • match()
  • replace()
var str = "1a2b3c4d5e6f7";
/*
 * split()
 * 	- 可以将一个字符串拆分为一个数组
 * 	- 方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串
 * 	- 这个方法即使不指定全局匹配,也会全都插分
 */

/*
 * 根据任意字母来将字符串拆分
 */
var result = str.split(/[A-z]/);


//console.log(result);

/*
 * search()
 * 	- 可以搜索字符串中是否含有指定内容
 * 	- 如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回-1
 * 	- 它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
 * 	- serach()只会查找第一个,即使设置全局匹配也没用
 */
str = "hello abc hello aec afc";
/*
 * 搜索字符串中是否含有abc 或 aec 或 afc
 */
result = str.search(/a[bef]c/);

//console.log(result);


/*
 * match()
 * 	- 可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
 * 	- 默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索
 * 		我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
 * 		可以为一个正则表达式设置多个匹配模式,且顺序无所谓
 * 	- match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果
 * 
 * 	
 */
str = "1a2a3a4a5e6f7A8B9C";

result = str.match(/[a-z]/ig);

//console.log(result[2]);

/*
 * replace()
 * 	- 可以将字符串中指定内容替换为新的内容
 *  - 参数:
 * 		1.被替换的内容,可以接受一个正则表达式作为参数
 * 		2.新的内容
 *  - 默认只会替换第一个
 */
//result = str.replace(/[a-z]/gi , "@_@");
result = str.replace(/[a-z]/gi , "");

//console.log(result);

🍀宿主对象

DOM

节点

在这里插入图片描述
节点属性
在这里插入图片描述
文档节点(document)

  • 文档节点document,代表的是整个HTML文档,网页中的所有节点都是它的子节点。
  • document对象作为window对象的属性存在的,我们不用获取可以直接使用。
  • 通过该对象我们可以在整个文档访问内查找节点对象,并可以通过该对象创建各种节点对象。

元素节点(Element)

  • HTML中的各种标签都是元素节点,这也是我们最常用的一个节点。
  • 浏览器会将页面中所有的标签都转换为一个元素节点,我们可以通过document的方法来获取元素节点。
  • 比如:
    – document.getElementById()
    – 根据id属性值获取一个元素节点对象。

文本节点(Text)

  • 文本节点表示的是HTML标签以外的文本内容,任意非HTML的文本都是文本节点。
  • 它包括可以字面解释的纯文本内容。
  • 文本节点一般是作为元素节点的子节点存在的。
  • 获取文本节点时,一般先要获取元素节点。在通过元素节点获取文本节点。
  • 例如:
    – 元素节点.firstChild;
    – 获取元素节点的第一个子节点,一般为文本节点

属性节点(Attr)

  • 属性节点表示的是标签中的一个一个的属性,这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。
  • 可以通过元素节点来获取指定的属性节点。
  • 例如:
    – 元素节点.getAttributeNode(“属性名”);
  • 注意:我们一般不使用属性节点。

事件

  • 事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。
  • JavaScript 与 HTML 之间的交互是通过事件实现的。
  • 对于 Web 应用来说,有下面这些代表性的事件:
    点击某个元素、将鼠标移动至某个元素上方、按下键盘上某个键,等等。

<button id="btn" onmousemove="alert('讨厌,你点我干嘛!');">我是一个按钮</button>
<button onclick="this.innerHTML=Date()">现在的时间是?</button>

<button id="btn">我是一个按钮</button>
var btn = document.getElementById("btn");
btn.onclick = function(){
	alert("你还点~~~");
};

<button onclick="displayDate()">现在的时间是?</button>
/*
 * onload事件会在整个页面加载完成之后才触发
 * 为window绑定一个onload事件
 * 		该事件对应的响应函数将会在页面加载完成之后执行,
 * 		这样可以确保我们的代码执行时所有的DOM对象已经加载完毕了
 * 	
 */
window.onload = function(){
	//获取id为btn的按钮
	var btn = document.getElementById("btn");
	//为按钮绑定一个单击响应函数
	btn.onclick = function(){
		alert("hello");
	};
};

获取元素节点

  • 通过document对象调用

getElementsByClassName() 可以根据class属性值获取一组元素节点对象,
但是该方法不支持IE8及以下的浏览器
//var box1 = document.getElementsByClassName("box1");

方法描述
document.getElementById(id)通过id属性获取一个元素节点对象
document.getElementsByTagName(name)通过标签名获取一组元素节点对象
document.getElementsByClassName(name)通过name属性获取一组元素节点对象
//为id为btn01的按钮绑定一个单击响应函数
var btn01 = document.getElementById("btn01");
btn01.onclick = function(){
	//查找#bj节点
	var bj = document.getElementById("bj");
	//打印bj
	//innerHTML 通过这个属性可以获取到元素内部的html代码
	alert(bj.innerHTML);
};



//为id为btn02的按钮绑定一个单击响应函数
var btn02 = document.getElementById("btn02");
btn02.onclick = function(){
	//查找所有li节点
	//getElementsByTagName()可以根据标签名来获取一组元素节点对象
	//这个方法会给我们返回一个类数组对象,所有查询到的元素都会封装到对象中
	//即使查询到的元素只有一个,也会封装到数组中返回
	var lis = document.getElementsByTagName("li");
	
	//打印lis
	//alert(lis.length);
	
	//变量lis
	for(var i=0 ; i<lis.length ; i++){
		alert(lis[i].innerHTML);
	}
};

//为id为btn03的按钮绑定一个单击响应函数
var btn03 = document.getElementById("btn03");
btn03.onclick = function(){
	//查找name=gender的所有节点
	var inputs = document.getElementsByName("gender");
	
	//alert(inputs.length);
	
	for(var i=0 ; i<inputs.length ; i++){
		/*
		 * innerHTML用于获取元素内部的HTML代码的
		 * 	对于自结束标签,这个属性没有意义
		 */
		//alert(inputs[i].innerHTML);
		/*
		 * 如果需要读取元素节点属性,
		 * 	直接使用 元素.属性名
		 * 		例子:元素.id 元素.name 元素.value
		 * 		注意:class属性不能采用这种方式,
		 * 			读取class属性时需要使用 元素.className
		 */
		alert(inputs[i].className);
	}
};

图片切换练习

传送
在这里插入图片描述

获取元素节点的子节点

传送门

• 通过具体的元素节点调用

  1. getElementsByTagName()
    方法,返回当前节点的指定标签名后代节点
  2. childNodes
    属性,表示当前节点的所有子节点
  3. children
    属性可以获取当前元素的所有子元素
  4. firstChild
    属性,表示当前节点的第一个子节点
  5. lastChild
    属性,表示当前节点的最后一个子节点
//为id为btn04的按钮绑定一个单击响应函数
var btn04 = document.getElementById("btn04");
btn04.onclick = function(){
	
	//获取id为city的元素
	var city = document.getElementById("city");
	
	//查找#city下所有li节点
	var lis = city.getElementsByTagName("li");
	
	for(var i=0 ; i<lis.length ; i++){
		alert(lis[i].innerHTML);
	}
	
};
  • childNodes属性会获取包括文本节点在呢的所有节点
    根据DOM标签标签间空白也会当成文本节点
  • 注意:在IE8及以下的浏览器中,不会将空白文本当成子节点,所以该属性在IE8中会返回4个子元素而其他浏览器是9个
//为id为btn05的按钮绑定一个单击响应函数
var btn05 = document.getElementById("btn05");
btn05.onclick = function(){
	//获取id为city的节点
	var city = document.getElementById("city");
	//返回#city的所有子节点
	var cns = city.childNodes;
	
	//alert(cns.length);
	
	/*for(var i=0 ; i<cns.length ; i++){
		alert(cns[i]);
	}*/
	
	/*
	 * children属性可以获取当前元素的所有子元素
	 */
	var cns2 = city.children;
	alert(cns2.length);
};
  • firstElementChild获取当前元素的第一个子元素
    firstElementChild不支持IE8及以下的浏览器,如果需要兼容他们尽量不要使用
//为id为btn06的按钮绑定一个单击响应函数
var btn06 = document.getElementById("btn06");
btn06.onclick = function(){
	//获取id为phone的元素
	var phone = document.getElementById("phone");
	//返回#phone的第一个子节点
	//phone.childNodes[0];
	//firstChild可以获取到当前元素的第一个子节点(包括空白文本节点)
	var fir = phone.firstChild;
	
	//firstElementChild获取当前元素的第一个子元素 
	//fir = phone.firstElementChild;
	
	alert(fir);
};

获取父节点和兄弟节点

• 通过具体的节点调用

  1. parentNode
    – 属性,表示当前节点的父节点
  2. previousSibling
    – 属性,表示当前节点的前一个兄弟节点
    previousElementSibling IE8不兼容
  3. nextSibling
    – 属性,表示当前节点的后一个兄弟节点

元素节点的属性

  • 获取,元素对象.属性名
    • 例:element.value
    • element.id
    • element.className

  • 设置,元素对象.属性名=新的值
    • 例:element.value = “hello”
    • element.id = “id01”
    • element.className = “newClass”

其他属性

• nodeValue (文本节点调用)
– 文本节点可以通过nodeValue属性获取和设置文本节点的内容
• innerHTML
– 元素节点通过该属性获取和设置标签内部的html代码
• innerText (文本父节点调用)

//获取id为bj的元素
var bj = document.getElementById("bj");

//alert(bj.innerHTML);
//alert(bj.innerText); 

//获取bj中的文本节点
/*var fc = bj.firstChild;
alert(fc.nodeValue);*/

alert(bj.firstChild.nodeValue);

全选练习

传送门
是否被选中属性
在这里插入图片描述

items[i].checked = true;


/*
 * 全选/全不选 多选框
 * 	- 当它选中时,其余的也选中,当它取消时其余的也取消
 * 
 * 在事件的响应函数中,响应函数是给谁绑定的this就是谁
 */
//为checkedAllBox绑定单击响应函数
checkedAllBox.onclick = function(){
	
	//alert(this === checkedAllBox);
	
	//设置多选框的选中状态
	for(var i=0; i <items.length ; i++){
		items[i].checked = this.checked;
	}
	
};

dom查询其他方法

//获取body标签
//var body = document.getElementsByTagName("body")[0];

/*
 * 在document中有一个属性body,它保存的是body的引用
 */
var body = document.body;
/*
 * document.documentElement保存的是html根标签
 */
var html = document.documentElement;
/*
 * document.all代表页面中所有的元素
 */
var all = document.all;

//console.log(all.length);

/*for(var i=0 ; i<all.length ; i++){
	console.log(all[i]);
}*/

使用CSS选择器进行查询

  • querySelector()
  • querySelectorAll()
  • 这两个方法都是用document对象来调用,两个方法使用相同,都是传递一个选择器字符串作为参数,方法会自动根据选择器字符串去网页中查找元素。
  • 不同的地方是querySelector()只会返回找到的第一个元素,而
    querySelectorAll()会返回所有符合条件的元素。

🌿节点的修改

传送门

  • 这里的修改我们主要指对元素节点的操作。

  • 创建节点
    – document.createElement(标签名)

  • 删除节点
    – 父节点.removeChild(子节点)

  • 替换节点
    – 父节点.replaceChild(新节点 , 旧节点)

  • 插入节点
    – 父节点.appendChild(子节点)
    – 父节点.insertBefore(新节点 , 旧节点)

//创建一个"广州"节点,添加到#city下
myClick("btn01",function(){
	//创建广州节点 <li>广州</li>
	//创建li元素节点
	/*
	 * document.createElement()
	 * 	可以用于创建一个元素节点对象,
	 * 	它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,
	 * 	并将创建好的对象作为返回值返回
	 */
	var li = document.createElement("li");
	
	//创建广州文本节点
	/*
	 * document.createTextNode()
	 * 	可以用来创建一个文本节点对象
	 *  需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回
	 */
	var gzText = document.createTextNode("广州");
	
	//将gzText设置li的子节点
	/*
	 * appendChild()
	 * 	 - 向一个父节点中添加一个新的子节点
	 * 	 - 用法:父节点.appendChild(子节点);
	 */
	li.appendChild(gzText);
	
	//获取id为city的节点
	var city = document.getElementById("city");
	
	//将广州添加到city下
	city.appendChild(li);
});
//将"广州"节点插入到#bj前面
myClick("btn02",function(){
	//创建一个广州
	var li = document.createElement("li");
	var gzText = document.createTextNode("广州");
	li.appendChild(gzText);
	
	//获取id为bj的节点
	var bj = document.getElementById("bj");
	
	//获取city
	var city = document.getElementById("city");
	
	/*
	 * insertBefore()
	 * 	- 可以在指定的子节点前插入新的子节点
	 *  - 语法:
	 * 		父节点.insertBefore(新节点,旧节点);
	 */
	city.insertBefore(li , bj);
	
	
});
//使用"广州"节点替换#bj节点
myClick("btn03",function(){
	//创建一个广州
	var li = document.createElement("li");
	var gzText = document.createTextNode("广州");
	li.appendChild(gzText);
	
	//获取id为bj的节点
	var bj = document.getElementById("bj");
	
	//获取city
	var city = document.getElementById("city");
	
	/*
	 * replaceChild()
	 * 	- 可以使用指定的子节点替换已有的子节点
	 * 	- 语法:父节点.replaceChild(新节点,旧节点);
	 */
	city.replaceChild(li , bj);
});
//删除#bj节点
myClick("btn04",function(){
	//获取id为bj的节点
	var bj = document.getElementById("bj");
	//获取city
	var city = document.getElementById("city");
	
	/*
	 * removeChild()
	 * 	- 可以删除一个子节点
	 * 	- 语法:父节点.removeChild(子节点);
	 * 		
	 * 		子节点.parentNode.removeChild(子节点);
	 */
	//city.removeChild(bj);
	
	bj.parentNode.removeChild(bj);
});
				
  • 使用innerHTML也可以完成DOM的增删改的相关操作
myClick("btn07",function(){
	
	//向city中添加广州
	var city = document.getElementById("city");
	
	/*
	 * 使用innerHTML也可以完成DOM的增删改的相关操作
	 * 一般我们会两种方式结合使用
	 */
	//city.innerHTML += "<li>广州</li>";
	
	//创建一个li
	var li = document.createElement("li");
	//向li中设置文本
	li.innerHTML = "广州";
	//将li添加到city中
	city.appendChild(li);
	
});

练习:表格增删

传送门
在这里插入图片描述

//点击超链接以后需要删除超链接所在的那行
//这里我们点击那个超链接this就是谁
//获取当前tr
var tr = this.parentNode.parentNode;

window对象方法

🌿dom操作css

操作内联样式

元素.style.样式名 = 样式值
修改被import修饰的样式 -->传送门

//为按钮绑定单击响应函数
var btn01 = document.getElementById("btn01");
btn01.onclick = function(){
	
	//修改box1的宽度
	/*
	 * 通过JS修改元素的样式:
	 * 	语法:元素.style.样式名 = 样式值
	 * 
	 * 注意:如果CSS的样式名中含有-,
	 * 		这种名称在JS中是不合法的比如background-color
	 * 		需要将这种样式名修改为驼峰命名法,
	 * 
	 * 我们通过style属性设置的样式都是内联样式,
	 * 	而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示
	 * 
	 * 但是如果在样式中写了!important,则此时样式会有最高的优先级,
	 * 	即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效
	 * 	所以尽量不要为样式添加!important
	 */
	box1.style.width = "300px";
	box1.style.height = "300px";
	box1.style.backgroundColor = "yellow";
	
};
获取元素当前样式
  • box1.currentStyle.width : 只有IE浏览器支持,其他的浏览器都不支持
/*
 * 获取元素的当前显示的样式
 * 	语法:元素.currentStyle.样式名
 * 它可以用来读取当前元素正在显示的样式
 * 	如果当前元素没有设置该样式,则获取它的默认值
 * 
 * currentStyle只有IE浏览器支持,其他的浏览器都不支持
 */

//alert(box1.currentStyle.width);
//box1.currentStyle.width = "200px";
//alert(box1.currentStyle.backgroundColor);
  • getComputedStyle() :是window的方法,可以直接使用
/*
 * 在其他浏览器中可以使用
 * 		getComputedStyle()这个方法来获取元素当前的样式
 * 		这个方法是window的方法,可以直接使用
 * 需要两个参数
 * 		第一个:要获取样式的元素
 * 		第二个:可以传递一个伪元素,一般都传null
 * 
 * 该方法会返回一个对象,对象中封装了当前元素对应的样式
 * 	可以通过对象.样式名来读取样式
 * 	如果获取的样式没有设置,则会获取到真实的值,而不是默认值
 * 	比如:没有设置width,它不会获取到auto,而是一个长度
 * 
 * 但是该方法不支持IE8及以下的浏览器
 * 
 * 通过currentStyle和getComputedStyle()读取到的样式都是只读的,
 * 	不能修改,如果要修改必须通过style属性
 */
//var obj = getComputedStyle(box1,null);

/*alert(getComputedStyle(box1,null).width);*/
//正常浏览器的方式
//alert(getComputedStyle(box1,null).backgroundColor);
var w = getStyle(box1,"width");

/*
 * 定义一个函数,用来获取指定元素的当前的样式
 * 参数:
 * 		obj 要获取样式的元素
 * 		name 要获取的样式名
 */

function getStyle(obj , name){
	//属性没找到返回undefined
	if(window.getComputedStyle){
		//正常浏览器的方式,具有getComputedStyle()方法
		return getComputedStyle(obj , null)[name];
	}else{
		//IE8的方式,没有getComputedStyle()方法
		return obj.currentStyle[name];
	}
	
	//return window.getComputedStyle?getComputedStyle(obj , null)[name]:obj.currentStyle[name];

}
获取其他样式属性

传送门

属性 / 方法描述
element.clientHeight返回元素的可见高度。
element.clientWidth返回元素的可见宽度。
element.offsetHeight返回元素的高度。
element.offsetWidth返回元素的宽度。
element.offsetLeft返回元素的水平偏移位置。
element.offsetTop返回元素的垂直偏移位置。
element.offsetParent返回元素的偏移容器。
element.scrollHeight返回元素的整体高度。
element.scrollLeft返回元素左边缘与视图之间的距离。
element.scrollTop返回元素上边缘与视图之间的距离。
element.scrollWidth返回元素的整体宽度。
  • 这些属性都是不带px的,返回都是一个数字,可以直接进行计算
  • 这些属性都是只读的,不能修改
/*
* clientWidth
* clientHeight
* 	- 这两个属性可以获取元素的可见宽度和高度
* 	- 这些属性都是不带px的,返回都是一个数字,可以直接进行计算
* 	- 会获取元素宽度和高度,包括内容区和内边距
*  - 这些属性都是只读的,不能修改
*/
//alert(box1.clientWidth);
//alert(box1.clientHeight);
//box1.clientHeight = 300;
/*
 * offsetWidth
 * offsetHeight
 * 	- 获取元素的整个的宽度和高度,包括内容区、内边距和边框
 */
//alert(box1.offsetWidth);
/*
 * offsetParent
 * 	- 可以用来获取当前元素的定位父元素
 *  - 会获取到离当前元素最近的开启了定位的祖先元素
 * 		如果所有的祖先元素都没有开启定位,则返回body
 */
var op = box1.offsetParent;

//alert(op.id);

/*
 * offsetLeft
 * 	- 当前元素相对于其定位父元素的水平偏移量
 * offsetTop
 * 	- 当前元素相对于其定位父元素的垂直偏移量
 */

//alert(box1.offsetLeft);
/*
 * scrollWidth
 * scrollHeight
 * 	- 可以获取元素整个滚动区域的宽度和高度
 */
//alert(box4.clientHeight);
//alert(box4.scrollWidth);

/*
 * scrollLeft
 * 	- 可以获取水平滚动条滚动的距离
 * scrollTop
 * 	- 可以获取垂直滚动条滚动的距离
 */
//alert(box4.scrollLeft);
//alert(box4.scrollTop);

//alert(box4.clientHeight); // 283

//当满足scrollHeight - scrollTop == clientHeight
//说明垂直滚动条滚动到底了

//当满足scrollWidth - scrollLeft == clientWidth
//说明水平滚动条滚动到底
//alert(box4.scrollHeight - box4.scrollTop); // 600

事件

知识传送门

获取div内鼠标坐标

在这里插入图片描述

  • 在IE8中,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的
    event = event || window.event;
  • clientX可以获取鼠标指针的水平坐标,cilentY可以获取鼠标指针的垂直坐标
var areaDiv = document.getElementById("areaDiv");
var showMsg = document.getElementById("showMsg");
areaDiv.onmousemove = function(event){
	//解决事件对象的兼容性问题
	event = event || window.event;
	
	var x = event.clientX;
	var y = event.clientY;
	
	//在showMsg中显示鼠标的坐标
	showMsg.innerHTML = "x = "+x + " , y = "+y;
};

div随鼠标移动

代码传送门
在这里插入图片描述
重点关注

  • 获取事件对象的兼容性问题
//解决兼容问题
event = event || window.event;
  • 获取pageX以及pageY的兼容性处理方法
  • 如何兼容scrollTop,以及scrollLeft中对父子元素选定状态不同的情况
//获取滚动条滚动的距离
/*
* chrome认为浏览器的滚动条是body的,可以通过body.scrollTop来获取
* 火狐等浏览器认为浏览器的滚动条是html的,
*/
var st = document.body.scrollTop || document.documentElement.scrollTop;
var sl = document.body.scrollLeft || document.documentElement.scrollLeft;
//var st = document.documentElement.scrollTop;

//获取到鼠标的坐标
/*
 * clientX和clientY
 * 	用于获取鼠标在当前的可见窗口的坐标
 * div的偏移量,是相对于整个页面的
 *
 * pageX和pageY可以获取鼠标相对于当前页面的坐标
 * 	但是这个两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用
 */
var left = event.clientX;
var top = event.clientY;

//设置div的偏移量
box1.style.left = left + sl + "px";
box1.style.top = top + st + "px";

事件冒泡

在这里插入图片描述

  • 可以将事件对象的cancelBubble设置为true,即可取消冒泡
    event.cancelBubble = true;
//为s1绑定一个单击响应函数
var s1 = document.getElementById("s1");
s1.onclick = function(event){
	event = event || window.event;
	alert("我是span的单击响应函数");
	
	//取消冒泡
	//可以将事件对象的cancelBubble设置为true,即可取消冒泡
	event.cancelBubble = true;
};

事件委派

  • 指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素从而通过祖先元素的响应函数来处理事件。
  • 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能

代码传送门
在这里插入图片描述

window.onload = function(){
	var u1 = document.getElementById("u1");
	//点击按钮以后添加超链接
	var btn01 = document.getElementById("btn01");
	btn01.onclick = function(){
		//创建一个li
		var li = document.createElement("li");
		li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>";
		//将li添加到ul中
		u1.appendChild(li);
	}
	var allA = document.getElementsByTagName("a");
	//为ul绑定一个单击响应函数
	u1.onclick = function(event){
		event = event || window.event;
		//可以使用正则判断hasClass
		if(event.target.className == "link"){
			alert("我是ul的单击响应函数");
		}	
	};
};
/*
 * 判断一个元素中是否含有指定的class属性值
 * 	如果有该class,则返回true,没有则返回false
 * 	
 */
function hasClass(obj, cn) {

	//判断obj中有没有cn class
	//创建一个正则表达式
	//var reg = /\bb2\b/;
	var reg = new RegExp("\\b" + cn + "\\b");

	return reg.test(obj.className);

}

事件绑定

  • 使用 对象.事件 = 函数 的形式绑定响应函数,它只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的
  • addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数(不支持IE8及以下的浏览器)
  • attachEvent() 在IE8中可以使用attachEvent()来绑定事件
    不同的是它是后绑定先执行,执行顺序和addEventListener()相反
/*
 * addEventListener()
 * 	- 通过这个方法也可以为元素绑定响应函数
 *  - 参数:
 * 		1.事件的字符串,不要on
 * 		2.回调函数,当事件触发时该函数会被调用
 * 		3.是否在捕获阶段触发事件,需要一个布尔值,一般都传false
 * 
 * 使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数,
 * 	这样当事件被触发时,响应函数将会按照函数的绑定顺序执行
 * 这个方法不支持IE8及以下的浏览器
 */
btn01.addEventListener("click",function(){
	alert(1);
},false);
/*
 * attachEvent()
 * 	- 在IE8中可以使用attachEvent()来绑定事件
 *  - 参数:
 * 		1.事件的字符串,要on
 * 		2.回调函数
 * 
 *  - 这个方法也可以同时为一个事件绑定多个处理函数,
 * 		不同的是它是后绑定先执行,执行顺序和addEventListener()相反
 */
btn01.attachEvent("onclick",function(){
	alert(1);
});

定义一个函数,用来为指定元素绑定响应函数
obj.addEventListener 是否有该方法使用哪个方式
addEventListener()中的this,是绑定事件的对象
attachEvent()中的this,是window
外套一层匿名函数,在中调用回调函数并指定this对象

//定义一个函数,用来为指定元素绑定响应函数
/*
 * addEventListener()中的this,是绑定事件的对象
 * attachEvent()中的this,是window
 *  需要统一两个方法this
 */
/*
 * 参数:
 * 	obj 要绑定事件的对象
 * 	eventStr 事件的字符串(不要on)
 *  callback 回调函数
 */
function bind(obj , eventStr , callback){
	if(obj.addEventListener){
		//大部分浏览器兼容的方式
		obj.addEventListener(eventStr , callback , false);
	}else{
		/*
		 * this是谁由调用方式决定
		 * callback.call(obj)
		 */
		//IE8及以下
		obj.attachEvent("on"+eventStr , function(){
			//在匿名函数中调用回调函数
			callback.call(obj);
		});
	}
}

事件传播

* 事件的传播
* 	- 关于事件的传播网景公司和微软公司有不同的理解
* 	- 微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,
* 		然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。
*  - 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,
* 		然后在向内传播给后代元素
* 	- W3C综合了两个公司的方案,将事件传播分成了三个阶段
* 		1.捕获阶段
* 			- 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
* 		2.目标阶段
* 			- 事件捕获到目标元素,捕获结束开始在目标元素上触发事件
* 		3.冒泡阶段
* 			- 事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件
* 
* 		- 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true
* 			一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false
* 
* 	- IE8及以下的浏览器中没有捕获阶段

拖拽

代码传送门
在这里插入图片描述

拖拽的流程
1.当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
3.当鼠标松开时,被拖拽元素固定在当前位置 onmouseup

兼容性处理

  1. 在IE8中,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的

    event = event || window.event; 
    
  2. setCapture():当鼠标点击后捕获所有的事件到该事件下

    只有IE支持,但是在火狐中调用时不会报错,而如果使用chrome调用,会报错

    obj.setCapture && obj.setCapture();
    

    同理releaseCapture():当鼠标抬起时释放捕获的事件

    obj.releaseCapture && obj.releaseCapture();
    
    /*
     * 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
     *     此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
     *     如果不希望发生这个行为,则可以通过return false来取消默认行为
     * 
     * 但是这招对IE8不起作用
     */
    return false;
    

细节处理

鼠标在元素中的位置,鼠标的坐标 - 元素的偏移量 = 鼠标在元素中的偏移量

//div的偏移量 鼠标.clentX - 元素.offsetLeft
//div的偏移量 鼠标.clentY - 元素.offsetTop
var ol = event.clientX - obj.offsetLeft;
var ot = event.clientY - obj.offsetTop;

鼠标移动时,元素的定位位置与鼠标位置相同,但需要计算出对应之前的偏移量(即鼠标在元素中的位置)

//当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
//获取鼠标的坐标 : 不用考虑出现滚动条的问题了
var left = event.clientX - ol;
var top = event.clientY - ot; //

//修改box1的位置
obj.style.left = left+"px";
obj.style.top = top+"px";

结构

	<body>
		
		我是一段文字
		
		<div id="box1"></div>
		
		<div id="box2"></div>
		
		<img src="img/an.jpg" id="img1" style="position: absolute;"/>
	</body>

滚动事件

代码传送门
实验需求: 给box添加鼠标滚动事件,让盒子边长变短
在这里插入图片描述

  1. 获取事件兼容处理
event = event || window.event;
  1. 绑定滚动事件兼容性处理
  • onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,但是火狐不支持该属性
  • 在火狐中需要使用 DOMMouseScroll 来绑定滚动事件,注意该事件需要通过addEventListener()函数来绑定

window.onload = function(){
  var box1 = document.getElementById("box1");
  box1.onmousewheel = function(event){
    //xxxxxx
  }
  //为火狐绑定滚轮事件
  bind(box1,"DOMMouseScroll",box1.onmousewheel);
};

function bind(obj , eventStr , callback){
  if(obj.addEventListener){
    //大部分浏览器兼容的方式
    obj.addEventListener(eventStr , callback , false);
  }else{
    /*
					 * this是谁由调用方式决定
					 * callback.call(obj)
					 */
    //IE8及以下
    obj.attachEvent("on"+eventStr , function(){
      //在匿名函数中调用回调函数
      callback.call(obj);
    });
  }
}
  1. 滚轮方向兼容性处理
//event.wheelDelta 可以获取鼠标滚轮滚动的方向
//向上滚 120   向下滚 -120
//wheelDelta这个值我们不看大小,只看正负

//wheelDelta这个属性火狐中不支持
//在火狐中使用event.detail来获取滚动的方向
//向上滚 -3  向下滚 3
//alert(event.detail);

/*
 * 当鼠标滚轮向下滚动时,box1变长
 *     当滚轮向上滚动时,box1变短
 */
//判断鼠标滚轮滚动的方向
if(event.wheelDelta > 0 || event.detail < 0){
   //向上滚,box1变短
   box1.style.height = box1.clientHeight - 10 + "px";
   
}else{
   //向下滚,box1变长
   box1.style.height = box1.clientHeight + 10 + "px";
}
  1. 兼容阻止默认行为
/*
 * 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
 * 需要使用event来取消默认行为event.preventDefault();
 * 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错
 */
event.preventDefault && event.preventDefault();


/*
 * 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,
 * 这是浏览器的默认行为,如果不希望发生,则可以取消默认行为
 */
return false;

键盘事件

onkeydown
onkeyup
键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document

  • 使用keyCode获取按键值
 document.onkeydown = function(event){
    event = event || window.event;

    /*
     * 可以通过keyCode来获取按键的编码
     *     通过它可以判断哪个按键被按下
     * 除了keyCode,事件对象中还提供了几个属性
     *     altKey
     *     ctrlKey
     *     shiftKey
     *        - 这个三个用来判断alt ctrl 和 shift是否被按下
     *           如果按下则返回true,否则返回false
     */

    //console.log(event.keyCode);

    //判断一个y是否被按下
    //判断y和ctrl是否同时被按下
    if(event.keyCode === 89 && event.ctrlKey){
       console.log("ctrl和y都被按下了");
    }


 };
  • 取消默认行为
//console.log(event.keyCode);
//数字 48 - 57 ,小键盘是 96-105
//使文本框中不能输入数字
if(event.keyCode >= 48 && event.keyCode <= 57){
  //在文本框中输入内容,属于onkeydown的默认行为
  //如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中
  return false;
}

将按键存储在对象中或集合中

var map = {}; // You could also use an array
onkeydown = onkeyup = function(e){
    e = e || window.event; // to deal with IE
    map[e.keyCode] = e.type == 'keydown';
    /* insert conditional here */
}

test_keys(13, 16, 65)
test_keys('ctrl', 'shift', 'A')
test_key(65)
test_key('A')

if(test_keys('ctrl', 'shift')){
    if(test_key('A')){
        alert('Control Shift A');
    } else if(test_key('B')){
        alert('Control Shift B');
    } else if(test_key('C')){
        alert('Control Shift C');
    }
}


function test_key(selkey){
    var alias = {
        "ctrl":  17,
        "shift": 16,
        "A":     65,
        /* ... */
    };

    return key[selkey] || key[alias[selkey]];
}

function test_keys(){
    var keylist = arguments;

    for(var i = 0; i < keylist.length; i++)
        if(!test_key(keylist[i]))
            return false;

    return true;
}

Navigator

* BOM
*  - 浏览器对象模型
*  - BOM可以使我们通过JS来操作浏览器
*  -BOM中为我们提供了一组对象,用来完成对浏览器的操作
*  - BOM对象
*     Window
*        - 代表的是整个浏览器的窗口,同时window也是网页中的全局对象
*     Navigator
*        - 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
*     Location
*        - 代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
*     History
*        - 代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录
*           由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页
*           而且该操作只在当次访问时有效
*     Screen
*        - 代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息
* 
* 
*     这些BOM对象在浏览器中都是作为window对象的属性保存的,
*        可以通过window对象来使用,也可以直接使用

识别浏览器是哪个

* Navigator
*  - 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
*  - 由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了
*  - 一般我们只会使用userAgent来判断浏览器的信息,
*     userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,
*     不同的浏览器会有不同的userAgent
* 
* 火狐的userAgent
*  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0
* 
* Chrome的userAgent
*  Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
* 
* IE8
*  Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
* 
* IE9
*  Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
* 
* IE10
*  Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
* 
* IE11
*  Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
*  -IE11中已经将微软和IE相关的标识都已经去除了,所以我们基本已经不能通过UserAgent来识别一个浏览器是否是IE
var ua = navigator.userAgent;

console.log(ua);

if(/firefox/i.test(ua)){
	alert("你是火狐!!!");
}else if(/chrome/i.test(ua)){
	alert("你是Chrome");
}else if(/msie/i.test(ua)){
	alert("你是IE浏览器~~~");
}else if("ActiveXObject" in window){
	alert("你是IE11,枪毙了你~~~");
}
/*
 * 如果通过UserAgent不能判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息
 * 比如:ActiveXObject
 */
/*if("ActiveXObject" in window){
   alert("你是IE,我已经抓住你了~~~");
}else{
   alert("你不是IE~~~");
}*/

/*alert("ActiveXObject" in window);*/

History

对象可以用来操作浏览器向前或向后翻页


 * length
 * 	- 属性,可以获取到当成访问的链接数量
 
alert(history.length);


 * back()
 * 	- 可以用来回退到上一个页面,作用和浏览器的回退按钮一样
 
history.back();


 * forward()
 * 	- 可以跳转下一个页面,作用和浏览器的前进按钮一样

history.forward();


 * go()
 * 	- 可以用来跳转到指定的页面
 * 	- 它需要一个整数作为参数
 * 		1:表示向前跳转一个页面 相当于forward()
 * 		2:表示向前跳转两个页面
 * 		-1:表示向后跳转一个页面
 * 		-2:表示向后跳转两个页面
window.onload = function(){

	//获取按钮对象
	var btn = document.getElementById("btn");
	
	btn.onclick = function(){

		history.go(-2);
	};
};

Location

该对象中封装了浏览器的地址栏的信息

  • 如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)
alert(location);
//https://www.bilibili.com/video/BV1YW411T7GX?p=126&spm_id_from=pageDriver
  • 如果直接将location属性修改为一个完整的路径,或相对路径,

则我们页面会自动跳转到该路径,并且会生成相应的历史记录

location = "http://www.baidu.com";
location = "01.BOM.html";
  • assign() 用来跳转到其他的页面,作用和直接修改location一样
location.assign("http://www.baidu.com");
  • reload()

用于重新加载当前页面,作用和刷新按钮一样

如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面

location.reload(true);
  • replace()

可以使用一个新的页面替换当前页面,调用完毕也会跳转页面

不会生成历史记录,不能使用回退按钮回退

location.replace("01.BOM.html");

window 方法

定时调用

setInterval() :可以将一个函数,每隔一段时间执行一次

参数:
	1.回调函数,该函数会每隔一段时间被调用一次
	2.每次调用间隔的时间,单位是毫秒

返回值:
	返回一个Number类型的数据
	这个数字用来作为定时器的唯一标识
var timer = setInterval(function(){
  
  count.innerHTML = num++;
  
  if(num == 11){
     //关闭定时器 clearInterval()可以用来关闭一个定时器
     //方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器
     clearInterval(timer);
  }
  
},1000);

代码传送门
在这里插入图片描述
代码传送门
在这里插入图片描述

延时调用

延时调用

延时调用一个函数不马上执行,而是隔一段时间以后在执行,而且只会执行一次
延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次
延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择

var timer = setTimeout(function(){
   console.log(num++);
},3000);

//使用clearTimeout()来关闭一个延时调用
			clearTimeout(timer);

定时应用(一)

代码传送门
在这里插入图片描述

代码传送门
在这里插入图片描述

代码传送门
在这里插入图片描述

类的操作

通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面
这样的执行的性能是比较差的,而且这种形式当我们要修改多个样式时,也不太方便

//定义一个函数,用来向一个元素中添加指定的class属性值
/*
 * 参数:
 * 	obj 要添加class属性的元素
 *  cn 要添加的class值
 * 	
 */
function addClass(obj , cn){
	
	//检查obj中是否含有cn
	if(!hasClass(obj , cn)){
		obj.className += " "+cn;
	}
}
/*
 * 判断一个元素中是否含有指定的class属性值
 * 	如果有该class,则返回true,没有则返回false
 * 	
 */
function hasClass(obj , cn){
	
	//判断obj中有没有cn class
	//创建一个正则表达式
	//var reg = /\bb2\b/;
	var reg = new RegExp("\\b"+cn+"\\b");
	
	return reg.test(obj.className);
	
}
/*
 * 删除一个元素中的指定的class属性
 */
function removeClass(obj , cn){
	//创建一个正则表达式
	var reg = new RegExp("\\b"+cn+"\\b");
	
	//删除class
	obj.className = obj.className.replace(reg , "");
}
/*
 * toggleClass可以用来切换一个类
 * 	如果元素中具有该类,则删除
 * 	如果元素中没有该类,则添加
 */
function toggleClass(obj , cn){
	
	//判断obj中是否含有cn
	if(hasClass(obj , cn)){
		//有,则删除
		removeClass(obj , cn);
	}else{
		//没有,则添加
		addClass(obj , cn);
	}
}

二级菜单

代码传送门
在这里插入图片描述

JSON

 * JSON
 * 	- JS中的对象只有JS自己认识,其他的语言都不认识
 * 	- JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,
 * 		并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互
 * 	- JSON
 * 		- JavaScript Object Notation JS对象表示法
 * 		- JSONJS对象的格式一样,只不过JSON字符串中的属性名必须加双引号
 * 			其他的和JS语法一致
 * 		JSON分类:
 * 			1.对象 {}
 * 			2.数组 []
 * 
 * 		JSON中允许的值:
 * 			1.字符串
 * 			2.数值
 * 			3.布尔值
 * 			4.null
 * 			5.对象
 * 			6.数组
//创建一个对象


var arr = '[1,2,3,"hello",true]';

var obj2 = '{"arr":[1,2,3]}';

var arr2 ='[{"name":"孙悟空","age":18,"gender":"男"},{"name":"孙悟空","age":18,"gender":"男"}]';

/*
 * 将JSON字符串转换为JS中的对象
 * 	在JS中,为我们提供了一个工具类,就叫JSON
 * 	这个对象可以帮助我们将一个JSON转换为JS对象,也可以将一个JS对象转换为JSON
 */

var json = '{"name":"孙悟空","age":18,"gender":"男"}';

/*
 * json --> js对象
 * 	 JSON.parse()
 * 		- 可以将以JSON字符串转换为js对象
 * 		- 它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回
 */

var o = JSON.parse(json);
var o2 = JSON.parse(arr);

//console.log(o.gender);
//console.log(o2[1]);

var obj3 = {name:"猪八戒" , age:28 , gender:"男"};


/*
 * JS对象 ---> JSON
 * 	JSON.stringify()
 * 		- 可以将一个JS对象转换为JSON字符串
 * 		- 需要一个js对象作为参数,会返回一个JSON字符串
 */

var str = JSON.stringify(obj3);
//console.log(str);

/*
 * JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错
 */


var str3 = '{"name":"孙悟空","age":18,"gender":"男"}';

JSON.parse(str3);

var str = '{"name":"孙悟空","age":18,"gender":"男"}';

/*
 * eval()
 * 	- 这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回
 * 	- 如果使用eval()执行的字符串中含有{},它会将{}当成是代码块
 * 		如果不希望将其当成代码块解析,则需要在字符串前后各加一个()
 * 
 * 	- eval()这个函数的功能很强大,可以直接执行一个字符串中的js代码,
 * 		但是在开发中尽量不要使用,首先它的执行性能比较差,然后它还具有安全隐患
 */

var str2 = "alert('hello');";

var obj = eval("("+str+")");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悠闲的线程池

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值