st779779

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JavaScript基础内容

第2章 入门

2.1 如何写一段JS代码并运行

  • 写在行内
01.html: 
<input type="button" value="按钮" onclick="alert('Hello World')" />
  • 写在script标签中 *
02.html:
<head>
  <script>
    alert('Hello World!');
  </script>
</head>
  • 写在外部js文件中,在页面引入
03.html:
<script src="main.js"></script>
main.js:

alert('Hello World!');

注意点: 引用外部js文件的 script 标签中不可以再写JavaScript代码,即使写了也不会执行,没有作用

2.3 变量

2.3.1 什么是变量

  • 什么是变量

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

  • 为什么要使用变量

    使用变量可以方便的获取或者修改内存中的数据

变量就是存储数据的容器;

2.3.2 如何使用变量

  • var声明变量
var age;
  • 变量的赋值
var age;
age = 18;
  • 同时声明多个变量
var age, name, sex;
age = 10;
name = 'zs';
  • 同时声明多个变量并赋值
var age = 10, name = 'zs';

2.3.3 变量的命名规则和规范

  • 规则 - 必须遵守的,不遵守会报错

    • 由字母、数字、下划线、$符号组成,且不能以数字开头

    • 区分大小写

    • 不能是关键字和保留字,例如:for、while。

  • 规范 - 建议遵守的,不遵守不会报错

    • 变量名必须有意义
    • 遵守驼峰命名法。(首字母小写,后面单词的首字母需要大写。例如:userName、userPassword)
  • 下面哪些变量名不合法

    a	    
    1
    age18
    18age
    name
    $
    $name
    _sex
    &sex
    theworld  
    theWorld
    

name变量名,本身不是保留字/关键字, 建议少用。 name在有的浏览器中,是自动声明过的。

2.3.4 案例

  1. 交换两个变量的值
var a = '1';
var b = '2';
//  借助第三个变量
var c = a;
a=b;
b=c;
console.log(a,b);
  1. 不使用临时变量,交换两个数值变量的值
//第二种方式
var num1 = 10;
var num2 = 20;
//计算的方式:累加,然后相减
num1 = num1 + num2;//num1的结果是30
num2 = num1 - num2;//num2的结果是10
num1 = num1 - num2;//num1的结果是20
console.log(num1);
console.log(num2);

2.3.5 代码调试(输出变量)

  1. alert 弹框 :浏览器页面弹框
var num1 = 10;
alert(num1);
  1. console.log() 浏览器console控制台
var num1 = 10;
var num2 = 20;
console.log(num1);
console.log(num1, num2);
  1. document.write() 浏览器页面中
var num1 = 10;
document.write(num1);

2.4 数据类型

2.4.1 简单数据类型

Number、String、Boolean、Undefined、Null

获取变量的类型

typeof

var age = 18;
console.log(typeof age);  // 'number'
Number类型
  • 数值字面量:数值的固定值的表示法(数值直接量)

    110 1024 60.5

  • 浮点数(小数)

  • 浮点数的精度问题

浮点数
	var n = 5e-324;   // 科学计数法  5乘以10的-324次方  
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数
   var result = 0.1 + 0.2;    // 结果不是 0.3,而是:0.30000000000000004
   console.log(0.07 * 100);
   不要判断两个浮点数是否相等
  • 数值范围

    最小值:Number.MIN_VALUE,// 这个值为: 5e-324  5乘以10的-324次方
    最大值:Number.MAX_VALUE,// 这个值为: 1.7976931348623157e+308
    无穷大:Infinity
    无穷小:-Infinity
    
String类型

'abc' "abc" 单双引号引起来的一连串字符

  • 字符串字面量(直接量)

    '程序猿','程序媛', "老妈程序猿"

    思考:如何打印以下字符串。
    我是一个 "正直" 的人
    我很喜欢 "老妈 '程序猿' "

    注: 转义后单双引号 只能 就近和转义后的单双引号进行配对

  • 转义符

1498289626813

注: \b 退格符 \f又叫走纸或进纸或 换页符

var s = '我很喜欢   \"老妈  \'程序猿\'  \"';
console.log(s);
  • 字符串长度

length属性用来获取字符串的长度

var str = '老妈程序猿 Hello World';
console.log(str.length);
  • 字符串拼接

字符串拼接使用 + 连接

console.log(11 + 11);
console.log('hello' + ' world');
console.log('100' + '100');
console.log('11' + 11);
console.log('male:' + true);
  1. 两边只要有一个是字符串,那么+就是字符串拼接功能
  2. 两边如果都是数字,那么就是算术功能。
Boolean类型
  • Boolean字面量: true和false,区分大小写
  • 计算机内部存储:true为1,false为0
Undefined和Null
  1. undefined表示一个声明了没有赋值的变量,变量只声明的时候值默认是undefined
  2. null表示一个空,变量的值如果想为null,必须手动设置

注: 关于undefined和null是一个面试中很容易被问到的问题

2.4.2 复杂数据类型

​ Object 对象:保存很多数据的一种数据类型

后面详解;

题外话

如何使用谷歌浏览器,快速的查看数据类型?

字符串的颜色是黑色的,数值类型是蓝色的,布尔类型也是蓝色的,undefined和null是灰色的

console.log('ss',2,null,undefined,true);

2.5 注释

被注释的内容是不执行的,不管什么内容都不会运行;

单行注释

用来描述下面一个或多行代码的作用

// 这是一个变量
var name = 'hm';

多行注释

用来注释多条代码

/*
var age = 18;
var name = 'zs';
console.log(name, age);
*/

总结:

JS代码的书写,变量的声明方式,数据类型,注释;

第3章 数据类型转换

3.1 转换成字符串类型

  • toString()

    var num = 5;
    console.log(num.toString());
    
  • String()

    var s = null;
    console.log(s.toString());
    console.log(String(s));
    
    // String()函数存在的意义:有些值没有toString(),
    // 这个时候可以使用String()。比如:undefined和null
    
  • 拼接字符串方式

    num + "",当 + 两边一个操作符是字符串类型,一个操作符是其它类型的时候,会先把其它类型转换成字符串再进行字符串拼接,返回字符串

3.2 转换成数值类型

  • Number()

    var a = Number('1');
    var b = Number(1);
    var c = Number('c');
    var d = Number(null);
    var e = Number(undefined);
    
    console.log(a,b,c,d,e); // 1 1 NaN 0 NaN
    
    // Number()可以把任意值转换成数值,如果要转换的字符串中有一个不是数值的字符,返回NaN
    
  • parseInt()

    var a = parseInt('1.2df');
    var b = parseInt(1);
    var c = parseInt('c12');
    var d = parseInt(null);
    var e = parseInt(undefined);
    
    console.log(a,b,c,d,e); //1 1 NaN NaN NaN
    
    // 如果第一个字符是数字会解析,直到遇到非数字结束
    // 如果第一个字符不是数字或者符号就返回NaN
    
  • parseFloat()

    var a = parseFloat('1.2df');
    var b = parseFloat('1.3.4');
    var c = parseFloat('c12');
    var d = parseFloat(null);
    var e = parseFloat(undefined);
    
    console.log(a,b,c,d,e); //1.2 1.3 NaN NaN NaN
    
    // parseFloat() 把字符串转换成浮点数
    // parseFloat()和parseInt非常相似,
    // 不同之处在与parseFloat会解析第一个 . 遇到第二个.或者非数字结束
    // 如果解析的内容里只有整数,解析成整数
    
  • +,-,-0 等运算

    var str = '500';
    console.log(+str);		// 取正
    console.log(-str);		// 取负
    console.log(str - 0);   
    

3.3 转换成布尔类型

  • Boolean()
var a = Boolean('0');
var b = Boolean(0);
var c = Boolean('1');
var d = Boolean(null);
var e = Boolean(undefined);
var f = Boolean(NaN);

console.log(a,b,c,d,e,f); //true false true false false false

// 0、''(空字符串) 、null、 undefined 、NaN 会转换成false  其它都会转换成true

总结:

字符串、数值及布尔类型的数据类型转换

第4章 操作符

表达式:值和操作符,运算会有一个结果;

同时,表达式中的每个数值及部分表达式,又称为 子表达式

4.1 算术运算符

+ - * / %  取余(取模)

4.2 一元运算符 *

一元运算符:只有一个操作数的运算符,一元运算会直接修改原始变量的数据;

5 + 6 两个操作数的运算符 二元运算符

++ 自身加 (自增)

-- 自身减 (自减)

  • 前置++

    var num1 = 5;
    ++ num1; 
    
    var num2 = 6;
    console.log(num1 + ++ num2); //13
    
  • 后置++

    var num1 = 5;
    num1 ++;    
    var num2 = 6 
    console.log(num1 + num2 ++); //12
    
  • 猜猜看

    var a = 1; 
    var b = ++a + ++a; 
    console.log(b); //5
    
    var a = 1; 
    var b = a++ + ++a; 
    console.log(b);//4
    
    var a = 1; 
    var b = a++ + a++; 
    // console.log(b);  // 3
    
    var a = 1; 
    var b = ++a + a++; 
    console.log(b);//4
    

    总结
    前置++:先加1,后参与运算
    后置++:先参与运算,后加1

    后置++ 运算的两个条件,满其一就会执行

    1:整个表达式结束;2表达式没结束但是又被使用了;

    上面两个理解后,下面两个自通
    前置-- :先减1,后参与运算
    后置-- :先参与运算,后减1

4.3 逻辑运算符(布尔运算符) *

&& 与 左边为真则取右边,左边为假则取左边
|| 或 左边为真则取左边,左边为假则边右边
!  非  取反
var a = 1;
var b = 2;
var c = 0;

console.log(a || b); //1
console.log(b || a); //2
console.log(c && a); //0
console.log(a || c && b); //1

// JS逻辑运算中的逻辑或和逻辑与的运算结果:
// 决定整个表达式的子表达式的值

4.4 关系运算符(比较运算符)

<  >  >=  <= == != === !==
==与===的区别:==只进行值得比较,===类型和值同时相等,则相等

var result = '55' == 55;  	// true
var result = '55' === 55; 	// false 值相等,类型不相等
var result = 55 === 55; 	// true

4.5 赋值运算符

注意与数学符号的差别;

= += -= *= /= %=

例如:
var num = 0;
num += 5;	//相当于  num = num + 5;

4.6 运算符的优先级 *

优先级从高到底
1. ()  优先级最高
2. 一元运算符  ++   --   !
3. 算数运算符  先*  /  %   后 +   -
4. 关系运算符  >   >=   <   <=
5. 相等运算符   ==   !=    ===    !==
6. 逻辑运算符 先&&   后||
7. 赋值运算符
// 练习1:
var s = 4 >= 6 || '人' != '阿凡达' && !(12 * 2 == 144) && true
console.log(s); //true

// 练习2:
var num = 10;
var f = 5 == num / 2 && (2 + 2 * num)
console.log(f.toString() === 22) //false

总结:

操作符的使用,基本数学运算,一元运算符自增自减及前置后置的区别,逻辑运算符及取值,关系比较运算符,赋值运算符,运算符优先级;

第5章 流程控制

程序的三种基本结构

顺序结构: 从上到下执行的代码就是顺序结构

程序默认就是由上到下顺序执行的;

分支结构:根据不同的情况及判断,执行对应代码;

循环结构:重复执行一段代码;

5.1 分支结构

if语句

语法结构

if (/* 条件表达式 */) {
  // 执行语句
}

if (/* 条件表达式 */){
  // 成立执行语句
} else {
  // 否则执行语句
}

if (/* 条件1 */){
  // 成立执行语句
} else if (/* 条件2 */){
  // 成立执行语句
} else if (/* 条件3 */){
  // 成立执行语句
} else {
  // 最后默认执行语句
}

案例

//获取两个数字中的最大值
var num1=100;
var num2=20;
if(num1>num2){
    console.log(num1);
}else{
    console.log(num2);
}
// 判断一个数是偶数还是奇数
var n = 10;
if(n%2==0){
    console.log('偶数');
}else{
    console.log('奇数');
}
    /*
    * 例子:
    * 获取考试的分数,如果成绩是在90(含)分以上的,则显示级别:A
    * 如果成绩是大于等于80的则:B
    * 如果成绩是大于等于70的则:C
    * 如果成绩是大于等于60的则:D
    * 如果成绩是小于60的则:E
    *
    * */


    var score = 91;
    if (score >= 90) {
        console.log("A");
    } else if (score >= 80) {
        console.log("B");
    } else if (score >= 70) {
        console.log("C");
    } else if (score >= 60) {
        console.log("D");
    } else {
        console.log("E");
    }

作业:判断一个年份是闰年还是平年

闰年:能被4整除,但不能被100整除的年份 或者 能被400整除的年份

var n = 2016;
if(n%4==0){
    if(n%100 !=0){
        console.log('闰年');
    }else if(n%400 ==0){
        console.log('闰年');
    }else{
        console.log('平年');
    }
}else{
    console.log('平年');
}
三元运算符
表达式1 ? 表达式2 : 表达式3
是对if……else语句的一种简化写法

案例:

// 是否年满18岁
var age = 18;
var s = age>=18?'Yes':'no';
console.log(s);
// 从两个数中找最大值
var a1 = 110;
var a2 = 19;
var s = a1>a2?a1:a2;
console.log(s);
switch语句

语法格式:

switch (expression) {
  case 常量1:
    语句;
    break;
  case 常量2:
    语句;
    break;
  …
  case 常量n:
    语句;
    break;
  default:
    语句;
    break;
}

/*
* 执行过程:
* 获取表达式的值,和值1比较,相同则执行代码1,遇到break跳出整个语句,结束
* 如果和值1不匹配,则和值2比较,相同则执行代码2,遇到break跳出整个语句,结束
* 如果和值2不匹配,则和值3比较,相同则执行代码3,遇到break跳出整个语句,结束
* 如果和值3不匹配,则和值4比较,相同则执行代码4,遇到break跳出整个语句,结束
* 如果和之前的所有的值都不一样,则直接执行代码5,结束
*/
break可以省略,如果省略,代码会继续执行下一个case
switch 语句在比较值时使用的是全等操作符, 因此不会发生类型转换(例如,字符串'10' 不等于数值 10)
/* *
* 判断这个人的成绩的级别:
* 如果是A,则提示,分数在90分以上
* 如果是B,则提示,分数在80分以上
* 如果是C,则提示,分数在70分以上
* 如果是D,则提示,分数在60分以上
* 否则提示,不及格
* */

var jiBie="B";
switch (jiBie){
    case "A" : 
        console.log("分数在90分以上的");
        break;
    case "B" : 
        console.log("分数在80分以上的");
        break;
    case "C" : 
        console.log("分数在70分以上的");
        break;
    case "D" : 
        console.log("分数在60分以上的");
        break;
    default :
        console.log("不及格");
}

5.2 循环结构

在JS语言中,循环语句有三种,while、do..while、for循环。

5.2.1 while语句

基本语法:

// 当循环条件为true时,执行循环体,
// 当循环条件为false时,结束循环。
while (循环条件) {
  //循环体
}

案例1:计算1-100之间所有数的和

// 初始化变量
var i = 1;
var sum = 0;
// 判断条件
while (i <= 100) {
  // 循环体
  sum += i;
  // 自增
  i++;
}
console.log(sum);

案例2:打印100以内 7的倍数

var i = 1;
while(i<100){
    if(i%7==0){
        console.log(i);
    }
    i++;
}

案例3:打印100以内所有偶数

var i = 1;
while(i<=100){
    if(i%2==0){
        console.log(i);
    }
    i++;
}

案例4:打印100以内所有偶数的和

var i = 1;
var s = 0;
while(i<=100){
    if(i%2==0){
        s = s+i;
    }
    i++;
}
console.log(s);

作业:
打印100以内的奇数
打印100以内的奇数的和

5.2.2 do...while语句

do..while循环和while循环非常像,二者经常可以相互替代,

但是do..while的特点是不管条件成不成立,都会执行一次。

do {
  // 循环体;
} while (循环条件);

案例:计算1+2+3+4+……+99+100 的结果

// 初始化变量
var i = 0;
var sum = 1;
do {
  sum += i;//循环体
  i++;//自增
} while (i <= 100);//循环条件

5.2.3 for语句

while和do...while一般用来解决无法确认次数的循环。for循环一般在循环次数确定的时候比较方便

for循环语法:

// for循环的表达式之间用的是;号分隔的,千万不要写成,
for (初始化表达式1; 判断表达式2; 自增表达式3) {
  // 循环体4
}

执行顺序:1243 ---- 243 -----243(直到循环条件变成false)

  1. 初始化表达式
  2. 判断表达式
  3. 自增表达式
  4. 循环体
//打印1-100之间所有数
for(var i=1;i<=100;i++){
    console.log(i);
}

//求1-100之间所有数的和
var s = 0;
for(var i=0;i<=100;i++){
    s+=i;
}
console.log(s);

//求1-100之间所有偶数的和
var s = 0;
for(var i=1;i<=100;i++){
    if(i%2==0){
        s+=i;
    }
}
console.log(s);

//打印正方形
var start = '';
for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    start += '* ';
  }
  start += '\n';
}
console.log(start);

//打印直角三角形
var start = '';
for (var i = 0; i < 10; i++) {
  for (var j = i; j < 10; j++) {
    start += '* ';
  }
  start += '\n';
}
console.log(start);

//打印9*9乘法表
var str = '';
for (var i = 1; i <= 9; i++) {
  for (var j = i; j <=9; j++) {
    str += i + ' * ' + j + ' = ' + i * j + '\t';
  }
  str += '\n';
}
console.log(str);

5.2.4 continue和break

break:立即跳出整个循环,即循环结束,开始执行循环后面的内容(直接跳到大括号)

continue:立即跳出当前循环,继续下一次循环(跳到i++的地方)

案例1:求1-100之间不能被7整除的整数的和(用continue)

var s = 0;
for(var i=0;i<100;i++){
    if(i%7==0){
        continue;
    }
    s+=i;
}
console.log(s);

案例2:求200-300之间所有的奇数的和(用continue)

var s = 0;
for(var i=200;i<=300;i++){
    if(i%2==0){
        continue;
    }else{
        s+=i;
    }
}
console.log(s);

案例3:求200-300之间第一个能被7整数的数(break)

for(var i=200;i<=300;i++){
    if(i%7==0){
        console.log(i);
        break;
    }
}

总结:

代码的执行流程分为顺序、分支和循环三种结构,顺序结构是默认的,判断结构主要有if-else和switch-case两种,循环结构有while、do-while、for三种,其中continue和break是跳出循环;

第6章 JS中特殊的对象-数组

之前学习的数据类型,只能存储一个值(比如:Number/String)。我们想在一个变量中存储多个值,应该如何存储?

所谓数组,就是将多个元素(通常是同一类型)按一定顺序排列放到一个集合中,那么这个集合我们就称之为数组。

6.1 数组的创建

// 字面量方式创建数组
var arr1 = []; //空数组
// 创建一个包含3个数值的数组,多个数组项以逗号隔开
var arr2 = [1, 3, 4]; 
// 创建一个包含2个字符串的数组
var arr3 = ['a', 'c']; 
console.log(arr1);
console.log(arr2);
console.log(arr3);

// 可以通过数组的length属性获取数组的长度
console.log(arr3.length);
// 可以设置length属性改变数组中元素的个数
arr3.length = 0;

console.log(arr3[0]);//undefined

数组的元素可以是任意类型的数据,因此,有时数组中的某个元素的值又是一个数组,而这样的数组被称为多维数组,如果数组中只有其他类型的数据,而没有另外的数组值,这样的数组被称为一维数组;

通常,数组被嵌套N层,则称为N维数组,最常见的就是二维数组、三维数组、四维数组,超过一维的数组都会被泛称为多维数组;

数组的维度值越大,复杂度就越高,开发中尽量避免产生高维度值的数组;

var arr1 = [a,b,c]; // 一维数组
var arr2 = [a,b,c,[d,e]]; // 二维数组
var arr3 = [a,b,c,[d,e,[f,g]]]; // 三维数组
var arr4 = [a,b,c,[d,e,[f,g,[h,t,y]]]]; // 四维数组

6.2 获取数组元素

// 格式:数组名[下标]	下标又称索引
// 下标从0开始
// 功能:获取数组对应下标的那个值,如果下标不存在,则返回undefined。
var arr = ['red',, 'green'];
arr[0];	// red
arr[1];	// undefined 下标位置没有数据
arr[2]; // green
arr[5]; // 这个数组的最大下标为2,因此返回undefined
// 获取多维数组的数据
var arr = ['路飞','娜美',['巴基','女帝',['佐助','乔巴']]];
console.log(arr[2][2][0]); //佐助

6.3 遍历数组

遍历:遍及所有,对数组的每一个元素都访问一次就叫遍历。

for循环数组遍历的基本语法:

for(var i = 0; i < arr.length; i++) {
	// 数组遍历的固定结构
}

for循环示例:

var arr1 = [1, 3, 4]; 

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

whil循环示例:

var arr1 = [1, 3, 4]; 

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

6.4 为数组修改添加元素

// 格式:数组名[下标/索引] = 值;
// 如果下标有对应的值,会把原来的值覆盖,如果下标不存在,会给数组新增一个元素。
var arr = ["red", "green", "blue"];
// 把red替换成了yellow
arr[0] = "yellow";
// 给数组新增加了一个pink的值
arr[3] = "pink";

6.5 数组操作案例

案例1:求数组中的所有数的和

//求和
var arr = [10, 20, 30, 40, 50];
//定义变量存储和
var sum = 0;
for (var i = 0; i < arr.length; i++) {
    sum += arr[i];
}
console.log("和为:" + sum);

案例2:获取数组中的最大值

//最大值
var arr = [10, 20, 30, 40, 50, 60];
//假设这个变量中的值是最大的
var maxNum = arr[0];
//遍历数组
for (var i = 0; i < arr.length; i++) {
    //判断
    if (maxNum < arr[i]) {
        maxNum = arr[i];
    }
}
console.log("最大值是:" + maxNum);

案例3: 遍历出数组中所有的偶数

// 遍历出数组中所有的偶数
var arr = [1,2,3,4,5,6,7];
for(var i=0;i<arr.length;i++){
    //判断
    if(arr[i]%2==0){
        console.log(arr[i]);
    }
}

案例4:将数组转为字符串并以 | 分割

//把数组中的每个名字后面拼接一个|然后以字符串的方式输出
var names = ["卡卡西", "佐助", "凤姐", "鸣人", "黑崎一护"];
var str = "";//空的字符串,用来存储最后的拼接的结果的字符串
//不停的遍历数组的数据,并且拼接字符串
for (var i = 0; i < names.length - 1; i++) {
    str += names[i] + "|";//拼接字符串的方式
}
str += names[names.length - 1];
console.log(str);

总结:

数组就是多个数据的集合,有一维数组和多维数组之分,可以使用字面量方式创建数组,使用下标来获取数组元素数据,使用for或者while循环来遍历数组元素;

第7章 函数

把一段相对独立的具有特定功能的代码块封装起来,形成一个独立实体,就是函数,起个名字(函数名),在后续开发中可以反复调用

函数的作用就是封装一段代码,将来可以重复使用

7.1 函数的声明及调用

7.1.1 声明

  • 关键字声明
function 函数名(){
  // 函数体
}
  • 表达式声明
var fn = function() {
  // 函数体
}
  • 特点:

    函数声明的时候,函数体并不会执行,只要当函数被调用的时候才会执行。
    一个函数一般都特定的用来干 一件 事情

7.1.2 调用

  • 调用函数的语法:
函数名();
  • 特点:

    函数体只有在调用的时候才会执行,调用需要()进行调用。
    可以调用多次(重复使用)

// 声明函数
function sayHi() {
  console.log("吃了没?");
}
// 调用函数
sayHi();

// 求1-100之间所有数的和
function getSum() {
  var sum = 0;
  for (var  i = 0; i < 100; i++) {
    sum += i;
  }
  console.log(sum);
}
// 一段代码可以多次调用
getSum();
getSum();
getSum();

7.2 参数

  • 为什么要有参数
function getSum() {
  var sum = 0;
  for (var i = 1; i <= 100; i++) {
    sum += i;
  }
  console.log();
}

// 虽然上面代码可以重复调用,但是只能计算1-100之间的值
// 如果想要计算n-m之间所有数的和,应该怎么办呢?
  • 语法:
// 函数内部是一个封闭的环境,可以通过参数的方式,把外部的值传递给函数内部
// 带参数的函数声明
function 函数名(形参1, 形参2, 形参...){
  // 函数体
}

// 带参数的函数调用
函数名(实参1, 实参2, 实参3);
  • *形参和实参 **
  1. 形式参数:在声明一个函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值。我们可以给函数设置参数。这个参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。
  2. 实际参数:如果函数在声明时,设置了形参,那么在函数调用的时候就需要传入对应的参数,我们把传入的参数叫做实际参数,也叫实参。
function fn(a, b) {
  console.log(a + b);
}
var x = 5, y = 6;
fn(x,y); 
// x,y实参,有具体的值。
// 函数执行的时候会把x,y复制一份给函数内部的a和b,
// 函数内部的值是复制的新值,无法修改外部的x,y

JS 函数在调用时,允许传多个实参,就是实参个数可以比形参个数多;

7.3 函数的返回值

当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果返回进行后续的运算),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个值

返回值语法:

//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参...){
  //函数体
  return 返回值;
}

//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3);

*返回值详解: **
如果函数没有显示的使用 return语句 ,那么函数有默认的返回值:undefined
如果函数使用 return语句,那么跟再return后面的值,就成了函数的返回值
如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是:undefined
函数使用return语句后,这个函数会在执行完 return 语句之后停止并立即退出,也就是说return后面的所有其他代码都不会再执行。

7.4 函数相关的其它事情

7.4.1 匿名函数与自调用函数

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

匿名函数如何使用:

将匿名函数赋值给一个变量,这样就可以通过变量进行调用

var fun1 = function(){
    console.log(1);
}
fun1();

匿名函数如果没有任何变量来表示它,那么就不能直接调用来执行,因此可以通过匿名函数的自调用的方式来执行

(function () {
  alert(123);
})();

关于自执行函数(匿名函数自调用)的作用:防止全局变量污染。

7.4.2 函数本身也是值 *

function fn() {}
console.log(typeof fn);
  • 函数作为参数

因为函数也是一种值类型,可以把函数作为另一个函数的参数,在另一个函数中调用

function f1(f){
    f();
}
function f2(){
    console.log(2);
}
f1(f2); //2
  • 函数做为返回值

因为函数是一种类型,所以可以把函数可以作为返回值从函数内部返回。

function fn(b) {
  var a = 10;
  return function () {
    alert(a+b);
  }
}
var f = fn(5);
f();  //15

总结:

函数是一段代码的封装,可重复多次运行,函数的声明有表达式声明和关键字声明,使用 ·函数名()· 的方式进行调用,调用时传入的参数为实参,声明时的参数时形参,函数使用return返回值,函数可以是没有名字的匿名函数,函数本身也可以当做值使用;

第8章 作用域与JS代码的运行 *

作用域:变量可以起作用的范围和区域

8.1 全局变量和局部变量 *

  • 全局变量与全局作用域

    在任何地方都可以访问到的变量就是全局变量,全局变量所在的区域就是全局作用域

  • 局部变量

    只在固定的代码片段内可访问到的变量,最常见的例如函数内部的变量,就是局部变量。局部变量所在的区域就是局部作用域(函数作用域)

不使用var声明的变量是全局变量,不推荐使用。
变量退出作用域之后会销毁,全局变量关闭网页或浏览器才会销毁

8.2 变量提升

console.log(a); // undefined
var a = 2;
console.log(a); //   a is not defined
  • 变量提升

    定义变量的时候,变量的声明会被提升到作用域的最上面,变量的赋值不会提升。

  • 函数提升

    JavaScript解析器首先会把当前作用域的函数声明提前到整个作用域的最前面

f();
function f(){
    console.log(12); //12
}
var f = 1;
function f(){
    console.log(12); //12
}
// 由于函数提升在前,所以被变量声明替换了;
// 执行阶段,变量被复制为1,不再是一个函数,
f(); // f is not a function

注:不管是普通变量还是函数,尽量不要出现重名;

8.3 JS代码的运行 *

console.log(s); //undefined
var s = 2;

JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。

JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析(编译)过程和代码执行过程

预解析过程:

  1. 语法检查,如果有错误,直接停止后续步骤不再运行。

  2. 把变量和函数的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值和调用。

  3. 先提升变量后提升函数,如果函数和变量同名,则被替换;

代码执行过程

变量的赋值,函数的调用,循环判断等,根据代码由上往下顺序执行;

var a = 25;
function abc (){
  alert(a);//undefined
  var a = 10;
}
abc();


// 如果变量和函数同名的话,函数优先做提升
console.log(a);
function a() {
  console.log('aaaaa');
}
var a = 1;
console.log(a);

// 1、----------------
var num = 10;
fun();
function fun() {
    console.log(num); //undefined
    var num = 20;
}

// 2、----------------
var a = 18;
f1();
function f1() {
    var b = 9;
    console.log(a); //undefined
    console.log(b); // 9
    var a = '123'; 
}

8.4 词法作用域

变量的作用域是在定义时决定而不是执行时决定的,也就是说词法作用域取决于编译阶段,通过静态分析就能确定,因此词法作用域也叫做静态作用域。

在 js 中词法作用域规则:

  • 函数允许访问函数外的数据.
  • 整个代码结构中只有函数可以限定作用域.
  • 作用域规则首先使用提升规则分析
  • 如果当前作用规则中有名字了, 就不考虑外面的名字
var num = 123;
function foo() {
  console.log( num );
}
foo();

if ( false ) {
    var num = 123;
}
console.log( num ); // undefiend

也就是说:

函数内部可以访问函数外部的变量,但是函数外部不可以访问函数内部的变量;

函数内部如果有变量,则优先使用内部的变量,如果函数内部没有,才会使用函数外部的变量;

8.5 作用域链 *

只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。

将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
var a = 1;
function fn1(){
    function fn2(){
        function fn3(){
            console.log(a);
        }
        fn3();
    }
    fn2();
}
fn1();

var a = 1;
function fn1(){
    var a = 2;
    function fn2(){
        var a = 3;
        function fn3(){
            console.log(a);
        }
        fn3();
    }
    fn2();
}
fn1();

总结:

函数内部是JS代码的局部作用域,函数外部是全局作用域,JS 代码的运行分为与解析阶段和执行阶段,变量的声明实在与解析阶段的,所以变量存在提升,而变量只在自己的作用域中起作用,但是自己作用域是可以访问上级作用域的;

第9章 对象(Object)

9.1 什么是对象

万物皆对象

现实生活中:万物皆对象,对象是一个具体的事物,一个具体的事物就会有行为和特征。
举例: 一部车,一个手机
车是一类事物,门口停的那辆车才是对象
	特征:红色、四个轮子
	行为:驾驶、刹车

9.2 JavaScript中的对象

JavaScript中的对象其实就是生活中对象的一个抽象
JavaScript的对象是无序属性的集合。
其属性可以包含基本值、对象、数组或函数。
对象就是一组没有顺序的值。
我们可以把JavaScript中的对象想象成键值对,其中值可以是数据和函数。
对象的行为和特征
	特征---属性
	行为---方法

事物的特征在对象中用属性来表示。

事物的行为在对象中用方法来表示。

属性和方法统称为对象的成员。

9.3 如何得到一个对象

  • 字面量方式创建对象

    var obj1 = {};//得到一个空对象
    var obj2 = {name:'张三',age:18};//得到拥有两个属性的对象
    //得到拥有两个属性和一个方法的对象
    var obj3 = {
        name:'张三',
        age:18,
        fei:function(){
            console.log('你上天啊!');
        }
    }
    
  • new Object() 创建对象 (内置构造函数)

    var person = new Object();
    
    person.name = 'lisi';
    person.age = 35;
    person.sayHi = function(){
        console.log('Hello,everyBody');
    }
    
  • 自定义构造函数创建对象

    function Person(name,age,job){
          this.name = name;
          this.age = age;
          this.job = job;
          this.sayHi = function(){
            console.log('Hello,everyBody');
          }
    }
    var p1 = new Person('张三', 22, 'actor');
    

new关键字和构造函数

构造函数 ,是一种特殊的函数,又叫做函数构造器。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。

  1. 构造函数用于创建一类对象,首字母通常大写。

  2. 构造函数要和new一起使用才有意义。

  3. new 关键字也读做实例化。实例化构造函数,得到一个对象。

9.4 this 的指向

JavaScript中的this指向问题,比较复杂,有时候会让人难以捉摸,随着学习的深入,我们会不断接触this,

在学习过程中,我们可以不断总结,最终搞清楚this在何种情况下指向何处……

目前,我们只需要记住以下两点就可以了:

1: 函数如果在某个对象下,this就指向这个对象

2: 函数如果被直接调用,this指向window对象

var o1 = {
    name: '山治',
    f: function () {
        console.log(this.name);
    }
}
o1.f(); // 山治
function f(){
    console.log(this);
}
f();
console.log(window);

9.5 对象的使用

  • 方法及属性的使用
对象.方法名(); //调用对象的方法
对象.属性;   //获取对象的属性
  • 遍历对象的属性

通过for..in语法可以遍历一个对象

var obj1 = {
    name:'路飞',
    age : 17,
    sex : '男',
}

for(var k in obj1){
    console.log(k);
    console.log(obj1[k]);
}

注意:使用for …in语法,同样可以遍历数组

注意:如果属性名或方法名,是一个变量,则使用对象[变量名] 语法

  • 删除对象的属性
var obj1 = {
    name:'路飞',
    age : 17,
    sex : '男',
}

console.log(obj1.age); //17
delete obj1.age;  //删除对象中指定的属性
console.log(obj1.age); // undefined

总结:

创建对象有三种方式,字面量、new内置构造函数及自定义构造函数;对象中有属性及方法,this指向当前对象,使用 . (点) 语法调用属性及方法;

第10章 标准库对象(内置对象)

JavaScript 提供了很多个内置对象:Math/Array/Number/String/Boolean...

对象只是带有属性方法的特殊数据类型。

我们在学习时其实就是要记住对象的每个属性和方法怎么使用,代表什么含义;

技术问题,遇到分歧,去哪里查找资料:

火狐开发者社区--MDN

微软开发者社区--MSDN

10.1 Math对象

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math

10.1.1 常用属性和方法

Math 是一个内置对象, 它具有数学常数和函数的属性和方法。不是一个函数对象。

与其它全局对象不同的是, Math 不是一个构造函数.  Math 的所有属性和方法都是静态的.

跟数学相关的运算直接使用Math中的成员即可

console.log(Math.PI); //圆周率3.141592653589793
Math.random();//介于 0 和 1 之间的伪随机数。

Math.ceil(6.6);//获取大于或等于提供数值的最小整数--向上取整
Math.floor(8.8);//获取小于或等于提供数值的最大整数--向下取整
Math.round(9.9);//四舍五入
Math.max(10,20,15);//取多个值中的最大值
Math.min(10,20,15);//取多个值中的最小值
Math.pow(10,2);//返回x的y次幂
Math.sqrt(100);//求平方根

10.1.2 案例

  • 求10-20之间的随机数

    Math.floor(Math.random() * (max - min)) + min; 
    

10.1.3 属性方法对照表

Math对象的属性(常量)

属性(常量) 描述
Math.E 常量 数学常数 e。这是欧拉数,自然对数的底。
Math.LN2 常量 2 的自然对数。
Math.LN10 常量 10 的自然对数。
Math.LOG2E 常量 以 2 为底 e 的对数。
Math.LOG10E 常量 以 10 为底 e 的对数。
Math.PI 常量 Pi。这是圆的周长与直径的比值。
Math.SQRT1_2 常量 0.5 的平方根,或相当于 1 除以 2 的平方根。
Math.SQRT2 常量 2 的平方根。

Math对象的方法(函数)

方法(函数) 描述
Math.abs 函数 返回数字的绝对值。
Math.acos 函数 返回数字的反余弦值。
Math.acosh 函数 返回数字的双曲反余弦值(或反双曲余弦值)。
Math.asin 函数 返回数字的反正弦值。
Math.asinh 函数 返回数字的反双曲正弦。
Math.atan 函数 返回数字的反正切值。
Math.atan2 函数 将与 X 轴的角度(以弧度为单位)返回到由 y 和 x 坐标表示的点。
Math.atanh 函数 返回数字的反双曲正切。
Math.ceil 函数 返回大于或等于提供的数值表达式的最小整数。
Math.cos 函数 返回数字的余弦值。
Math.cosh 函数 返回数字的双曲余弦。
Math.exp 函数 返回 e(自然对数的底)的乘幂数。
Math.expm1 函数 返回 e(自然对数的底)的乘幂数减去 1 的结果。
Math.floor 函数 返回小于或等于提供的数值表达式的最大整数。
Math.hypot 函数 返回参数平方和的平方根。
Math.imul 函数 返回被视为 32 位带符号整数的两个数字的积。
Math.log 函数 返回数字的自然对数。
Math.log1p 函数 返回 1 加上一个数字的的自然对数。
Math.log10 函数 返回数字以 10 为底的对数。
Math.log2 函数 返回数字以 2 为底的对数。
Math.max 函数 返回提供的两个数值表达式中的较大值。
Math.min 函数 返回提供的两个数字中的较小值。
Math.pow 函数 返回基表达式的指定乘幂数的值。
Math.random 函数 返回介于 0 和 1 之间的伪随机数。
Math.round 函数 返回舍入到最近整数的指定数值表达式。
Math.sign 函数 返回数字符号,它指示数字为正数、负数还是 0。
Math.sin 函数 返回数字的正弦值。
Math.sinh 函数 返回数字的反双曲正弦。
Math.sqrt 函数 返回数字的平方根。
Math.tan 函数 返回数字的正切值。
Math.tanh 函数 返回数字的双曲正切。
Math.trunc 函数 返回数字的整数部分,删除任何小数数字。

10.2 Date对象(构造函数)

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date

10.2.1 常用属性和方法

创建 Date 实例用来处理日期和时间。Date 对象基于1970年1月1日(世界标准时间)起的毫秒数。

// 获取当前时间,UTC世界时间,距1970年1月1日(世界标准时间)起的毫秒数
var now = new Date();
console.log(now.getTime());	// 获取距1970年1月1日(世界标准时间)起的毫秒数
console.log(now.valueOf());	// valueOf用于获取对象的原始值,与getTime()方法相同

Date构造函数的参数
1. 毫秒数 1498099000356		new Date(1498099000356)
2. 日期格式字符串  '2015-5-1'	 new Date('2015-5-1')
3. 年、月、日……				  new Date(2015, 4, 1)   // 月份从0开始
  • 获取日期的毫秒形式
var now = new Date();
console.log(now.getTime());
// valueOf用于获取对象的原始值
console.log(now.valueOf());

// HTML5中提供的方法,有兼容性问题
var now = Date.now();

// 不支持HTML5的浏览器,可以用下面这种方式
var now = + new Date();	// 隐式调用 Date对象的valueOf() 
  • 日期格式化方法
toString()		// 转换成字符串
valueOf()		// 获取毫秒值
// 下面格式化日期的方法,在不同浏览器可能表现不一致,一般不用
toDateString()
toTimeString()
toLocaleDateString()
toLocaleTimeString()
  • 获取日期指定部分
getTime()  	  // 返回毫秒数和valueOf()结果一样,valueOf()内部调用的getTime()
getSeconds()  // 返回0-59
getMinutes()  // 返回0-59
getHours()    // 返回0-23
getDay()      // 返回星期几 0周日   6周6
getDate()     // 返回当前月的第几天
getMonth()    // 返回月份,***从0开始***
getFullYear() //返回4位的年份  如 2016

10.2.2 案例

  • 案例1:写一个函数,格式化日期对象,返回yyyy-MM-dd HH:mm:ss的形式
function formatDate(d) {
  //如果date不是日期对象,返回
  if (!date instanceof Date) {
    return;
  }
  var year = d.getFullYear(),
      month = d.getMonth() + 1, 
      date = d.getDate(), 
      hour = d.getHours(), 
      minute = d.getMinutes(), 
      second = d.getSeconds();
  month = month < 10 ? '0' + month : month;
  date = date < 10 ? '0' + date : date;
  hour = hour < 10 ? '0' + hour : hour;
  minute = minute < 10 ? '0' + minute:minute;
  second = second < 10 ? '0' + second:second;
  return year + '-' + month + '-' + date + ' ' + hour + ':' + minute + ':' + second;
}
  • 计算时间差,返回相差的天/时/分/秒
function getInterval(start, end) {
  var day, hour, minute, second, interval;
  interval = end - start;
  interval /= 1000;
  day = Math.round(interval / 60 /60 / 24);
  hour = Math.round(interval / 60 /60 % 24);
  minute = Math.round(interval / 60 % 60);
  second = Math.round(interval % 60);
  return {
    day: day,
    hour: hour,
    minute: minute,
    second: second
  }
}

10.2.3 方法对照表

Date对象 的方法。

方法 描述
getDate 方法 使用当地时间返回一个月某天的值。
getDay 方法 使用当地时间返回一个星期某天的值。
getFullYear 方法 使用当地时间返回年份值。
getHours 方法 使用当地时间返回小时值。
getMilliseconds 方法 使用当地时间返回毫秒值。
getMinutes 方法 使用当地时间返回分钟值。
getMonth 方法 使用当地时间返回月份值。
getSeconds 方法 使用当地时间返回秒值。
getTime 方法 Date 对象中的时间值返回为自 1970 年 1 月 1 日午夜起经过的毫秒数。
getTimezoneOffset 方法 返回主机的时间与协调通用时间 (UTC) 之间的分钟差值。
getUTCDate 方法 使用 UTC 返回一个月某天的值。
getUTCDay 方法 使用 UTC 返回一个星期某天的值。
getUTCFullYear 方法 使用 UTC 返回年份值。
getUTCHours 方法 使用 UTC 返回小时值。
getUTCMilliseconds 方法 使用 UTC 返回毫秒值。
getUTCMinutes 方法 使用 UTC 返回分钟值。
getUTCMonth 方法 使用 UTC 返回月份值。
getUTCSeconds 方法 使用 UTC 返回秒值。
getVarDate 方法 Date 对象中的 VT_DATE 值返回。
getYear 方法 返回年份值。
hasOwnProperty 方法 返回一个布尔值,该值指示一个对象是否具有指定名称的属性。
isPrototypeOf 方法 返回一个布尔值,该值指示对象是否存在于另一个对象的原型链中。
propertyIsEnumerable 方法 返回一个布尔值,该值指示指定属性是否为对象的一部分以及该属性是否是可枚举的。
setDate 方法 使用当地时间设置一个月中某一日的数值。
setFullYear 方法 使用当地时间设置年份值。
setHours 方法 使用当地时间设置小时值。
setMilliseconds 方法 使用当地时间设置毫秒值。
setMinutes 方法 使用当地时间设置分钟值。
setMonth 方法 使用当地时间设置月份值。
setSeconds 方法 使用当地时间设置秒值。
setTime 方法 设置 Date 对象中的日期和时间值。
setUTCDate 方法 使用 UTC 设置一个月中某一日的数值。
setUTCFullYear 方法 使用 UTC 设置年份值。
setUTCHours 方法 使用 UTC 设置小时值。
setUTCMilliseconds 方法 使用 UTC 设置毫秒值。
setUTCMinutes 方法 使用 UTC 设置分钟值。
setUTCMonth 方法 使用 UTC 设置月份值。
setUTCSeconds 方法 使用 UTC 设置秒值。
setYear 方法 使用当地时间设置年份值。
toDateString 方法 以字符串值的形式返回一个日期。
toGMTString 方法 返回使用格林尼治标准时间 (GMT) 转换为字符串的日期。
toISOString 方法 以字符串值的形式返回采用 ISO 格式的日期。
toJSON 方法 用于在 JSON 序列化之前转换目标类型的数据。
toLocaleDateString 方法 将一个日期以字符串值的形式返回,该字符串应适合于宿主环境的当前区域设置。
toLocaleString 方法 返回使用当前区域设置转换为字符串的对象。
toLocaleTimeString 方法 以字符串值的形式返回一个时间,此字符串值应与宿主环境的当前区域设置相适应。
toString 方法 返回表示对象的字符串。
toTimeString 方法 以字符串值形式返回时间。
toUTCString 方法 返回使用 UTC 转换为字符串的日期。
valueOf 方法 返回指定对象的原始值。

10.3 Array对象

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array

10.3.1 常用属性和方法

length属性: 返回数组的成员数量。

var arr = ['a', 'b'];
console.log(arr.length) // 2

常用方法

  • push方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。

    var a = [];
    a.push(1) // 1
    a.push('a') // 2
    a.push(true, {}) // 4
    console.log(a); //[1, 'a', true, {}]
    
  • pop方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组

    var a = ['a', 'b', 'c'];
    a.pop() // 'c'
    console.log(a);// ['a', 'b']
    
  • slice方法用于提取原数组的一部分,返回一个新数组,原数组不变。

    它的第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素本身不包括在内)。 如果省略第二个参数,则一直返回到原数组的最后一个成员。

    var a = ['a', 'b', 'c'];
    a.pop() // 'c'
    console.log(a);// ['a', 'b']
    
  • join方法用于将数组元素以指定字符拼接为字符串,返回一个字符串,原数组不变。

    var a = ['a','b','c','d','e'];
    console.log(a.join('-')) // 'a-b-c-d-e'
    
  • 返回数组的字符串表示形式。

    var arr = [1, 2, 3, 4];
    console.log(arr.toString()); //1,2,3,4
    

10.3.2 方法和属性对照表

Array 对象的属性。

属性 描述
length 属性 返回一个整数值,此整数比数组中所定义的最高位元素大 1,是实际元素个数。

Array 对象的方法。

方法 描述
concat 方法(数组) 返回由两个数组组合而成的新数组。
entries 方法 返回包含数组的键/值对的迭代器。
every 方法 检查定义的回调函数是否为数组中的所有元素返回 true
fill 方法 使用指定值填充数组。
filter 方法 对数组的每个元素调用定义的回调函数,并返回回调函数为其返回 true 的值的数组。
findIndex 方法 返回满足回调函数中指定的测试条件的第一个数组元素的索引值。
forEach 方法 为数组中的每个元素调用定义的回调函数。
hasOwnProperty 方法 返回一个布尔值,该值指示某个对象是否具有指定名称的属性。
indexOf 方法(数组) 返回某个值在数组中的第一个匹配项的索引。
isPrototypeOf 方法 返回一个布尔值,该值指示某个对象是否存在于另一个对象的原型链中。
join 方法 返回由一个数组的所有元素串联而成的 String 对象。
keys 方法 返回包含数组的索引值的迭代器。
lastIndexOf 方法(数组) 返回指定值在数组中的最后一个匹配项的索引。
map 方法 对数组的每个元素调用定义的回调函数并返回包含结果的数组。
pop 方法 从数组中移除最后一个元素并将该元素返回。
propertyIsEnumerable 方法 返回一个布尔值,该值指示指定属性是否为对象的一部分且是否可枚举。
push 方法 将新元素追加到一个数组中,并返回数组的新长度。
reduce 方法 通过对数组中的所有元素调用定义的回调函数来累积单个结果。 回调函数的返回值是累积的结果,并且作为对回调函数的下一个调用中的参数提供。
reduceRight 方法 通过对数组中的所有元素调用定义的回调函数来按降序顺序累积单个结果。 回调函数的返回值是累积的结果,并且作为对回调函数的下一个调用中的参数提供。
reverse 方法 将元素顺序被反转的 Array 对象返回。
shift 方法 从数组中移除第一个元素并将返回该元素。
slice 方法(数组) 返回一个数组中的一部分。
some 方法 检查定义的回调函数是否为数组的任何元素返回 true
sort 方法 返回一个元素已经进行了排序的 Array 对象。
splice 方法 从一个数组中移除元素,如有必要,在所移除元素的位置上插入新元素,并返回所移除的元素。
toLocaleString 方法 返回使用当前区域设置的字符串。
toString 方法 返回数组的字符串表示形式。
unshift 方法 在数组的开头插入新元素。
valueOf 方法 获取对数组的引用。
values 方法 返回包含数组的值的迭代器。

10.4 String对象

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String

10.4.1 常用属性和方法

var s = 'JavaScript';
// length属性返回字符串的长度。
var i = s.length; //返回参数在字符串中第一次出现的位置
var i = s.indexOf('b'); //从原字符串取出子字符串并返回,不改变原字符串
var i = s.substr(2,4);//从下标第二个开始截取4个长度的字符串
//toLowerCase方法用于将一个字符串全部转为小写 
//toUpperCase则是全部转为大写
var i = s.toLowerCase();
var i = s.toUpperCase();

// 用于替换匹配的子字符串,只替换第一个匹配 
var i = s.replace('a','b');
console.log(i);

10.4.2 方法和属性对照表

String 对象的属性

属性 描述
constructor 属性 指定用于创建对象的函数。
length 属性(字符串) 返回 String 对象的长度。
prototype 属性 为对象的类返回原型的引用。

String 对象的方法。

方法 描述
anchor 方法 将具有 NAME 特性的 HTML 定位点放置在文本两侧。
big 方法 将 HTML 标记放置在文本两侧。
blink 方法 将 HTML 标记放置在文本两侧。
bold 方法 将 HTML 标记放置在文本两侧。
charAt 方法 返回指定索引处的字符。
charCodeAt 方法 返回指定字符的 Unicode 编码。
codePointAt 方法 返回一个 Unicode UTF-16 字符的码位。
concat 方法(字符串) 返回由提供的两个字符串串联而成的字符串。
EndsWith 方法 返回一个布尔值,该值指示字符串或子字符串是否以传入字符串结尾。
includes 方法 返回一个布尔值,该值指示传入字符串是否包含在字符串对象中。
fixed 方法 将 HTML 标记放置在文本两侧。
fontcolor 方法 将具有 COLOR 特性的 HTML 标记放置在文本两侧。
fontsize 方法 将具有 SIZE 特性的 HTML 标记放置在文本两侧。
hasOwnProperty 方法 返回一个布尔值,该值指示某个对象是否具有指定名称的属性。
indexOf 方法(字符串) 返回字符串内第一次出现子字符串的字符位置。
isPrototypeOf 方法 返回一个布尔值,该值指示某个对象是否存在于另一个对象的原型链中。
italics 方法 将 HTML 标记放置在文本两侧。
lastIndexOf 方法(字符串) 返回字符串内子字符串的最后一个匹配项。
link 方法 将具有 HREF 特性的 HTML 定位点放置在文本两侧。
localeCompare 方法 返回一个值,该值指示两个字符串在当前区域设置中是否相等。
match 方法 通过使用提供的正则表达式对象来搜索字符串并以数组形式返回结果。
normalize 方法 返回指定字符串的 Unicode 范式。
propertyIsEnumerable 方法 返回一个布尔值,该值指示指定属性是否为对象的一部分且是否可枚举。
repeat 方法 返回一个新的字符串对象,它的值等于重复了指定次数的原始字符串。
replace 方法 使用正则表达式替换字符串中的文本并返回结果。
search 方法 返回正则表达式搜索中第一个子字符串匹配项的位置。
slice 方法(字符串) 返回字符串的片段。
small 方法 将 HTML 标记放置在文本两侧。
split 方法 返回一个字符串拆分为若干子字符串时所产生的字符串数组。
StartsWith 方法 返回一个布尔值,该值指示字符串或子字符串是否以传入字符串开头。
strike 方法 将 HTML 标记放置在文本两侧。
sub 方法 将 HTML 标记放置在文本两侧。
substr 方法 返回一个从指定位置开始且具有指定长度的子字符串。
substring 方法 返回 String 对象中指定位置处的子字符串。
sup 方法 将 HTML 标记放置在文本两侧。
toLocaleLowerCase 方法 返回一个字符串,其中所有字母字符都转换为小写形式,并将考虑主机环境的当前区域设置。
toLocaleString 方法 返回使用当前区域设置转换为字符串的对象。
toLocaleUpperCase 方法 返回一个字符串,其中所有字母字符都转换为大写形式,并将考虑主机环境的当前区域设置。
toLowerCase 方法 返回一个字符串,其中所有字母字符都转换为小写形式。
toString 方法 返回字符串。
toUpperCase 方法 返回一个字符串,其中所有字母字符都转换为大写形式。
trim 方法 返回已移除前导空格、尾随空格和行终止符的字符串。
valueOf 方法 返回字符串。

10.5 包装对象

对象是 JavaScript 语言最主要的数据类型,三种原始类型的值——数值、字符串、布尔值——在一定条件下,也会自动转为对象,也就是原始类型的“包装对象”。

所谓“包装对象”,就是分别与数值、字符串、布尔值相对应的NumberStringBoolean三个原生对象。这三个原生对象可以把原始类型的值变成(包装成)对象。

var v1 = new Number(123);
var v2 = new String('abc');
var v3 = new Boolean(true);

typeof v1 // "object"
typeof v2 // "object"
typeof v3 // "object"

v1 === 123 // false
v2 === 'abc' // false
v3 === true // false

包装对象的最大目的,首先是使得 JavaScript 的对象涵盖所有的值,其次使得原始类型的值可以方便地调用某些方法。

原始类型的值,可以自动当作对象调用,即调用各种对象的方法和参数。

这时,JavaScript 引擎会自动将原始类型的值转为包装对象实例,在使用后立刻销毁实例。

比如,字符串可以调用length属性,返回字符串的长度。

'abc'.length // 3

上面代码中,abc是一个字符串,本身不是对象,不能调用length属性。

JavaScript 引擎自动将其转为包装对象,在这个对象上调用length属性。

调用结束后,这个临时对象就会被销毁。这就叫原始类型与实例对象的自动转换。

注意:JS的内置对象还有很多,我们只不过是学习了比较常用的几个而已;

在后面的学习中,我们还有讲解使用其他类型的内置对象;

可以查看狐火和微软开发者社区,获取更多知识……

课外知识:

JS代码规范&编程风格

  • 缩进:

    空格和tab键都可以,尽量保持一致,使用一种;

    两个空格和四个空格都行,尽量保持一致就行,但是使用4个空格的多一些;

  • 分号:

    尽量不要忘记,每一行的结束都要加分号

    while 与 for 循环后面不要加分号

    if else、switch等分支语句后面不要加分号

    关键字声明函数,后面不要加分号

    表达式声明函数,函数后面加分号

  • 区块:

    两种写法

if(){
    
}

if()
{
    
}

​ 理论上两种都可以,但是尽量使用第一种,因为js会在行尾自动添加分号,有时会出现意外情况;

  • 圆括号

    函数的声明和调用、表达式运算

    1:函数调用时,函数名和括号之间没有空格

    2:函数声明时,函数名和括号之间没有空格

    3:参与表达式运算时,括号的前面和后面,都要加空格

  • 变量的声明

    console.log(x);
    var x = 10;
    
    //等价于
    
    var x;
    console.log(x);
    x = 10;
    

    为了避免此种情况的出现,建议将所有在本作用域下声明的变量都提到最前面声明并赋值;

  • 自增自减运算

    因为 ++ 在前和++ 在后的运算结果不同,所以,尽量使用 +=1 -=1 替代,

    提高代码的可读性;

    你的团队中一定有搞不明白++在前和在后的区别的二傻子;生活不易,请善待他们;

  • 赋值 =

    赋值前后加空格;

变量命名和代码缩进 规范,是一个程序员必备的基本编程素质;

让别人给你调试BUG的第一前提条件就是 缩进要规范

JS基础-浏览器API

第0章 API介绍

HTML:用来存储网页内容;

CSS:用来定义这些内容的显示样式;

JavaScript:用来创造丰富的页面效果或者网页应用。

0.1 API 介绍

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

  • 任何开发语言都可以有自己的API
  • API的特征输入和输出(I/O)
  • API的使用方法

0.2 Web API 接口的概念

浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)

此处的Web API特指浏览器给JS提供的API(一组方法),Web API在后面的课程中有其它含义

前面我们说过,浏览器的API一共提供了三种类型;

分别是 浏览器操控类(BOM)、页面文档操控类(DOM)、网络控制类;

但实际上,浏览器提供的API并不只有这三类,而是有很多类:

文档对象模型、设备API、通信API、数据管理API、特权API、已认证应用程序的私有API;

第1章 文档对象模型 (DOM)

1.1 基本概念

DOM是JavaScript操作网页的接口,全称为“文档对象模型”(Document Object Model)。 它的作用是将网页转为一个JavaScript对象,从而可以用脚本进行各种操作(增删改查)。

浏览器会根据DOM模型,将结构化文档(比如HTML和XML)解析成一系列的节点, 再由这些节点组成一个树状结构(DOM Tree)。 所有的节点和最终的树状结构,都有规范的对外接口。

JavaScript是一门编程语言,而DOM是浏览器对HTML文档结构化后的一个模型;

严格地说,DOM不属于JavaScript,但是我们最常用的就是使用JavaScript操作DOM;

20180526-215645

1.2 节点的概念

DOM的最小组成单位叫做节点(node)。文档的树形结构(DOM树),就是由各种不同类型的节点组成。

每个节点都可以看作是文档树的一片叶子。

最顶层的节点就是document节点,它代表了整个文档;是文档的根节点。

每张网页都有自己的document节点,window.document属性就指向这个节点的。

只要浏览器开始载入HTML文档,这个节点对象就存在了,可以直接调用。

每一个HTML标签元素,在DOM树上都会转化成一个Element节点对象;

文档里面最高一层一般是HTML标签,其他HTML标签节点都是它的下级。

除了根节点以外,其他节点对于周围的节点都存在三种关系:

父节点关系(parentNode):直接的那个上级节点 
子节点关系(childNodes):直接的下级节点 
同级节点关系(sibling):拥有同一个父节点的节点

常用dom操作:

查找页面的标签元素

标签增加、修改、删除等操作

标签的属性相关操作

给标签元素绑定事件(设置当什么什么时候,做什么什么事情)

1.3 查找节点

上一节我们知道,整个文档的节点就是document节点,那么想要具体找到某个节点,
我们可以使用document提供的一系列方法:

<div>
	<p id="p1">1111111111</p>
	<i>2222222222</i>
	<p class='p'>1111111111</p>
	<i>2222222222</i>
	<p class="p">1111111111</p>
	<i>2222222222</i>
	<div id="p">
	    <p name="p">3333333333</p>
	</div>
</div>

getElementsByTagName()
返回所有指定HTML标签的元素,返回值是一个类似数组的HTMLCollection对象;匹配失败,返回[]
参数是想要获取节点的具体节点名称,就是 标签名;

var p = document.getElementsByTagName('p');
//标签节点.style.样式名 = '样式值'  可以给标签节点设置css样式
p[3].style.background = 'red';

getElementsByClassName()
返回所有class名字符合指定条件的元素,返回值是一个类似数组的HTMLCollection对象;匹配失败,返回[]
参数为 标签的class属性的值

var p = document.getElementsByClassName('p');
p[1].style.background = 'yellow';

getElementsByName()
选择拥有name属性的HTML元素,返回值是一个类似数组的HTMLCollection对象;匹配失败,返回[]
参数为 标签的name属性的值;
注意,使用时,最好选择原生具有name属性的元素;

var p = document.getElementsByName('p');
p[0].style.background = 'yellow';

getElementById()
返回匹配指定id属性的元素节点;没有发现匹配的节点,则返回null
参数为 标签的id属性的值,参数大小写敏感;

var p = document.getElementById('p');
p.style.background = 'yellow';

querySelector()、querySelectorAll()
document.querySelector方法接受一个CSS选择器作为参数,返回匹配该选择器的元素节点;
如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null;

document.querySelectorAll方法与querySelector用法类似,
区别是返回一个类似数组的HTMLCollection对象,包含所有匹配给定选择器的节点。

var p = document.querySelector('.p');
p.style.background = 'yellow';
var p = document.querySelectorAll('.p');
p[1].style.background = 'yellow';

多个参数值,使用,(英文逗号)隔开,而querySelector()返回第一个选中的节点;

var p = document.querySelectorAll('i,.p');
for(var i=0;i<p.length;i++){
    p[i].style.background = 'yellow';
}

这两个方法都支持复杂的CSS选择器。

//选中 id 属性值为p1的元素
// var p = document.querySelectorAll('[id="p1"]');
//选中div元素的class属相值为p的元素
// var p = document.querySelectorAll('div.p');
//选中所有的p标签,但是class值为p的除外
var p = document.querySelectorAll('p:not(.p)');

for(var i=0;i<p.length;i++){
    p[i].style.background = 'yellow';
}

但是,它们不支持CSS伪元素的选择器(比如:first-line和:first-letter)
和伪类的选择器(比如:link和:visited),即无法选中伪元素和伪类。

第2章 事件

2.1 什么是事件

一种 触发—响应 的机制;

用户的行为 + 浏览器感知(捕获)到用户的行为 + 事件处理程序

事件三要素:

  • 事件源:(被)触发事件的元素
  • 事件类型:事件的触发方式(例如鼠标点击或键盘点击)
  • 事件处理程序:事件触发后要执行的代码(函数形式)

2.2 事件绑定

  • 行内方式绑定(元素属性)
<body>
    <input type="button" value="按钮" id="btn" onclick="alert(2)">
</body>

<body>
    <input type="button" value="按钮" id="btn" onclick="f()">
</body>
<script>
    function f(){
        console.log(3);
    }
</script>

onclick 其实就是html元素的一个属性,而属性的值需要是 一段可执行的JS代码

  • 动态绑定 (节点对象属性)
<body>
    <input type="button" value="按钮" id="btn">
</body>
<script>
    var btn = document.getElementById('btn');
    btn.onclick = function(){
        alert(4);
    }
</script>

获取节点对象,然后 修改 节点对象属性 onclick 的值,值是一个 匿名函数 即可;

以上两种事件绑定方式,需要在事件名称前加 on ;

  • 事件监听(节点对象方法)
<body>
    <input type="button" value="按钮" id="btn">
</body>
<script>
    var btn = document.getElementById('btn');
    btn.addEventListener('click',function(){
        alert(5);
    });
</script>

每一个节点对象都提供了 addEventListener 方法,这个方法可以给选中的节点添加指定类型的事件及事件处理程序;

  • 移除事件监听
<body>
    <input type="button" value="按钮" id="btn">
</body>
<script>
    function f(){
        alert(5);
    }
    var btn = document.getElementById('btn');
    btn.addEventListener('click',f);
    btn.removeEventListener('click',f);
</script>

注意:
removeEventListener方法移除的监听函数,
必须与对应的addEventListener方法的参数完全一致,
而且必须在同一个元素节点,否则无效。

2.3 三种事件绑定比较

this关键字
在JavaScript中,每一个函数的内部都存在一个this关键字,其随着运行环境的不同,其指向也是不同的。

<body>
    <p id="t">ttttt</p>
</body>
<script>
    var d = document.getElementById('t');
    d.onclick = function(){
		//this指代本对象 就是 d 
        console.log(this);
    }
</script>

将上述代码的动态绑定,改为行内绑定:

<body>
    <p id="t" onclick="f()">ttttt</p>
</body>
<script>
    function f(){
        console.log(this); //window对象
    }
</script>

由此可知:
行内绑定,其事件处理程序内部的this指向了全局的window对象。
动态绑定,其事件处理程序内部的this指向了当前正在操作的dom对象。

需求:同一个元素的同一个事件,绑定多个处理函数:

<body>
    <!--行内绑定,谁在前谁执行-->
    <p id="t"  onclick="t()" onclick="f()">ttttt</p>
</body>
<script>
    function f(){
        alert(1);
    }
    function t(){
        alert(2);
    }
</script>
<body>
    <p id="t" >ttttt</p>
</body>
<script>
    //动态绑定,后边的执行函数会将前面的覆盖掉
    var d = document.getElementById('t');
    d.onclick = function(){
        alert(1);
    }
    d.onclick = function (){
        alert(2);
    }
</script>
<body>
    <p id="t" >ttttt</p>
</body>
<script>
    var d = document.getElementById('t');
    function f1() {
        console.log(this);
    }
    d.addEventListener('click', f1, false);
    d.addEventListener('click', function(){console.log('f2');}, false);
</script>

总结:
第一种 "HTML标签的on-属性",违反了HTML与JavaScript代码相分离的原则;处理函数中 this 指向的window对象;
第二种 "Element节点的事件属性" 的缺点是,同一元素同一个事件只能定义一个监听函数,也就是说,如果定义两次onclick属性,后一次定义会覆盖前一次。但是处理函数中的 this 指向的选中的对象;
第三种:addEventListener方法可以针对同一个元素的同一个事件,添加多个监听处理函数。处理函数中的 this 指向的也是选中的元素;

2.4 事件类型

事件类型一览表:

https://developer.mozilla.org/zh-CN/docs/Web/Events

2.3.1 页面事件(资源事件)

事件名称 何时触发
load 一个资源及其相关资源已完成加载。
<body onload="f1()" >
</body>
<script>
    function f1(){
        alert('f1');
    }
</script>

2.3.2 焦点事件

事件名称 何时触发
focus 元素获得焦点
blur 元素失去焦点
<body>
    <input type="text" id="t" value="请输入用户名" onfocus="f1()" onblur="f2()">
</body>
<script>
    function f1(){
        document.getElementById('t').value = '';
    }
    function f2(){
        var v = document.getElementById('t').value;
        alert(v);
    }
</script>

2.3.3 鼠标事件

事件名称 何时触发
mouseenter 指针移到有事件监听的元素内
mouseover 指针移到有事件监听的元素或者它的子元素内
mousemove 指针在元素内移动时持续触发
mousedown 在元素上按下任意鼠标按钮
mouseup 在元素上释放任意鼠标按键
click 在元素上按下并释放任意鼠标按键
dblclick 在元素上双击鼠标按钮
contextmenu 右键点击 (右键菜单显示前).
mouseleave 指针移出元素范围外(不冒泡)
mouseout 指针移出元素,或者移到它的子元素上
select 文本被选中(input标签、textarea标签)
copy 元素内容被拷贝时
 <body>
    <div id="d" style="width:200px;height:200px;border:1px solid red">
        来啊
    </div>
</body>
<script>
    var d = document.getElementById('d');
    //当鼠标悬浮时触发
    d.onmouseover = function(){
        console.log('来了?');
    }
	//当鼠标离开时触发
    d.onmouseout = function(){
        console.log('不要啊');
    }
	//当鼠标按下时触发
    d.onmousedown = function(){
        console.log('用力啊');            
    }
	//当鼠标弹起时触发
    d.onmouseup = function(){
        console.log('再来');            
    }
	//当鼠标移动时触发
    d.onmousemove = function(){
        console.log('别乱动');            
    }
    
    //当点击右键时
    d.oncontextmenu = function(){
        console.log('你想干什么?');
        return false;
    }
	
    // 当复制内容时
    d.oncopy = function(){
        console.log('你敢复制我?');
        return false;
    }
    
</script>

2.3.4 键盘事件

事件名称 何时触发
keydown 按下任意按键
keypress 除 Shift, Fn, CapsLock 外任意键被按住. (连续触发)
keyup 释放任意按键
<body>
    <input type="text"  value="" id="t">
</body>
<script>
    var d = document.getElementById('t');
    //当键盘按下时触发
    d.onkeydown = function(){
        console.log('推到?');
    }
    //当键盘按下时触发
    d.onkeypress = function(){
        console.log('撩起2?');
    }
    //当键盘弹起时触发
    d.onkeyup = function(){
        console.log('撩起?');
    }
</script>

2.3.5 form表单事件

Event Name Fired When
reset 点击重置按钮时 (<input type=’reset’ value=’重置’ />
submit 点击提交按钮
<body>
    <form id="f" action="1.2.5.php">
        姓名:<input type="text" name="" value=""> <br>
        <input type="submit" name="" value="提交">
        <input type="reset" name="" value="重置">
    </form>
</body>
<script>
    var d = document.getElementById('f');
	//当表单提交时触发
    d.onsubmit = function(){
        alert('t');
    }
	//当表单重置时触发
    d.onreset = function(){
        alert('re');
    }
</script>

2.3.6 内容变化事件

change: 当内容改变且失去焦点时触发 (存储事件)
input : 当内容改变时触发 (值变化事件)

<body>
    <input type="text" id="t" value="">
</body>
<script>
    var d = document.getElementById('t');
    //当内容改变且失去焦点时触发
    d.onchange = function(){
        console.log('t');
    }
    //当内容改变时触发
    d.oninput = function(){
        console.log('in');
    }
</script>

2.4 事件的传播

三个包裹着的DIV,都绑定了点击事件,问:
当点击 div1 时,会发生什么现象?

<head>
    <title></title>
    <meta charset="UTF-8">
    <style>
        div{padding: 40px}
        #div3{width: 300px;height: 300px;background-color: red}
        #div2{width: 200px;height: 200px;background-color: yellow}
        #div1{width: 100px;height: 100px;background-color: blue}
    </style>
</head>
<body>
    <div id="div3">3
        <div id="div2">2
            <div id="div1">1</div>
        </div>
    </div>
</body>
<script>
    var d1 = document.getElementById('div1');
    var d2 = document.getElementById('div2');
    var d3 = document.getElementById('div3');

    d1.onclick = function(){
        alert('1');
    }
    d2.onclick = function(){
        alert('2');
    }
    d3.onclick = function(){
        alert('3');
    }
</script>

20180528-183307

当点击div1时,触发 事件1,但是,紧跟着,事件2和事件3也被触发了;

这种现象,我们称为 事件冒泡

在JS中当一个事件发生以后,它会在不同的DOM节点之间传播。
这种传播分成三个阶段:
第一阶段:从window对象传导到目标节点,称为 捕获阶段
第二阶段:在目标节点上触发,称为 目标阶段
第三阶段:从目标节点传导回window对象,称为 冒泡阶段

20180528-183442

事件传播的最上层对象是window;
事件的传播顺序,在捕获阶段依次为window、document、html、body、div;
在冒泡阶段依次为div、body、html、document、window。

注意: 三种事件绑定方式全部 默认 监听冒泡阶段事件;

2.5 改变事件触发的阶段

想让事件监听在捕获阶段,只能通过 addEventListener 方法的进行设置:

<script>
    var d1 = document.getElementById('div1');
    var d2 = document.getElementById('div2');
    var d3 = document.getElementById('div3');
    d1.addEventListener('click',function(){
        alert('m1');
    });//目标阶段触发

    d2.addEventListener('click',function(){
        alert('b2');
    },true);//捕获阶段触发

    d3.addEventListener('click',function(){
        alert('b3');
    },true);//捕获阶段触发


    d1.addEventListener('click',function(){
        alert('mm1');
    });//目标阶段触发

    d2.addEventListener('click',function(){
        alert('p2');
    });//冒泡阶段触发
	d3.addEventListener('click',function(){
        alert('p3');
    },false);//冒泡阶段触发
</script>

2.6 案例

为选中的的元素绑定事件

<body>
<input type="button" value="按钮" id="btn" />
<script>
  //根据id获取元素
  document.getElementById("btn").onclick=function () {
      alert("哈哈,我又变帅了");
  };
</script>
</body>

一次性事件案例(下载按钮点一次则失效)

<body>
    <input type="button" id="btn" value="下载">
</body>
<script>
    var btn = document.getElementById('btn');
    function f(){
        alert(123);
        btn.removeEventListener('click',f);
    }
    
    btn.addEventListener('click',f);
</script>

点击每个图片弹出对话框

<body>
<img src="images/1-small.jpg" alt="" />
<img src="images/2-small.jpg" alt="" />
<img src="images/3-small.jpg" alt="" />
<script>
  //点击每个图片都可以弹出对话框
  //根据标签名字获取元素,分别注册点击事件,分别添加事件处理函数
  var imgObjs=document.getElementsByTagName("img");
  //遍历
  for(var i=0;i<imgObjs.length;i++){
    //为每个图片元素注册点击事件,添加事件处理函数
    imgObjs[i].onclick=function () {
      alert("啊,我被点击了");
    };

  }
</script>

</body>

第3章 节点操作

页面元素节点的操作,都离不开DOM对象

3.1 节点操作-增删改

document.createElement()
用来生成网页元素节点,参数为元素的标签名;

document.createTextNode()
用来生成文本节点,参数为所要生成的文本节点的内容;

node.appendChild()
接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点;

node.hasChildNodes()
返回一个布尔值,表示当前节点是否有子节点

node.removeChild()
接受一个子节点作为参数,用于从当前节点移除该子节点

node.cloneNode()
用于克隆一个选中的节点。
它接受一个布尔值作为参数,表示是否同时克隆子节点,默认是false,即不克隆子节点。
注意: 不会克隆绑定到该元素上的事件;

node.innerHTML
返回该元素包含的 HTML 代码。该属性可读写,常用来设置某个节点的内容;(不属于W3C DOM规范)

node.innerText

返回该元素包含的内容。该属性可读写

<body>
    <div id="d">
        <span>111</span>
    </div>
</body>
<script>
    //创建元素节点
    var p = document.createElement('p');
    //创建文本节点
    var t = document.createTextNode('女娲');
    //添加节点
    p.appendChild(t);
    var d = document.querySelector('#d')
    d.appendChild(p);

    //判断是否有子节点
    if(d.hasChildNodes('span')){
        var s = document.querySelector('span');
        //删除子节点
        d.removeChild(s);
    }

    // 克隆一个节点
    var c = d.cloneNode(true);
    d.appendChild(c);

	//操作选中元素的HTML代码,有值则是设置,无值则是获取
    alert(d.innerHTML);
    
    console.log(document.getElementById('d').innerText);
    console.log(document.getElementById('d').innerHTML);
</script>

案例:

点击按钮创建img节点,添加到body中

<body>
    <input type="button" value="我要图" id="btn">
</body>
<script>
    var btn = document.getElementById('btn');
    btn.onclick = function(){
        // var img = document.createElement('img');
        // img.src = '/img/c2.jpg';
        // document.getElementsByTagName('body')[0].appendChild(img);
        
        // 直接
        document.getElementsByTagName('body')[0].innerHTML += "<img src='/img/c3.jpg'>";
    }
</script>

动态创建文本框

<body>
    <input type="button" value="++" id="btn">
    <div id="bo"></div>
</body>
<script>
    var btn = document.getElementById('btn');
    btn.onclick = function () {
        // document.getElementById('bo').innerHTML += '<input type="text">';
        
        var inp = document.createElement('input');
        document.getElementById('bo').appendChild(inp);
    }
</script>

3.2 节点属性

3.2.1 原生属性

HTML元素节点的标准属性(即在标准中定义的属性),会自动成为元素节点对象的属性

<body>
    <div id="d" a="b" class="a b c d e"></div>
</body>
<script>

    var d = document.querySelector('#d');
    //获取原有属性值
    console.log(d.id);
    //修改原有属性值
    d.id = 'ff';
    console.log(d.a); // undefined
    //特殊:获取class类名,需使用className属性
  	console.log(d.className);
    d.className += ' hello';
</script>

3.2.2 属性操作的标准方法

node.getAttribute()
返回当前元素节点的指定属性。如果指定属性不存在,则返回null;

node.setAttribute()
为当前元素节点新增属性。如果同名属性已存在

<body>
    <div id="d"></div>
</body>
<script>
    var d = document.querySelector('#d');
    //设置属性,有则修改,无则添加,可设置非标准属性
    d.setAttribute('id','ffdd');
    d.setAttribute('aa','kk');
    //获取属性值,可获取非标准属性
    console.log(d.getAttribute('aa'));
</script>

node.hasAttribute()
返回一个布尔值,表示当前元素节点是否包含指定属性

node.removeAttribute()
从当前元素节点移除属性

//如果有id属性
if(d.hasAttribute('id')){
    //删除id属性
    d.removeAttribute('id');
}

3.3 节点操作-层级关系

node.nextElementSibling
返回紧跟在当前节点后面的第一个同级Element节点,如果当前节点后面没有同级节点,则返回null;

node.previousElementSibling
返回紧跟在当前节点前面的第一个同级Element节点,如果当前节点前面没有同级节点,则返回null;

node.parentElement
返回当前节点的父级Element节点;

node.childNodes
返回一个NodeList集合,成员包括当前节点的所有子节点(注意空格回车也算)。

node.firstChild

返回树中节点的第一个子节点,如果节点是无子节点,则返回 null。

node.lastChild

返回该节点的最后一个子节点,如果该节点没有子节点则返回null

<body>
    <div id="d1">
        <p id="p1">11111</p>
        <p id="p2">222</p>
        <p id="p3">33333</p>
        <p id="p4">4444</p>
    </div>
    <div id="d2">
        <p id="p5">55555</p>
        <p id="p6">66666</p>
    </div>
</body>
<script>
    var p2 = document.querySelector('#p2');
    //下一个兄弟节点
    p2.nextElementSibling.style.background = 'red';
    //上一个兄弟节点
    p2.previousElementSibling.style.background = 'red';
    //父级节点
    p2.parentElement.style.background = 'red';

    var d1 = document.querySelector('#d1');
	//所有子节点列表
    d1.childNodes[3].style.background = 'red';
</script>

3.4 CSS样式操作

每个DOM对象都有style属性,我们可以直接操作,用来读写 行内CSS样式
之前,我们已经简单的使用过JS控制元素的CSS样式;
在具体使用的时候还有一些需要重点注意的细节:

  1. 名字需要改写,将横杠从CSS属性名中去除,然后将横杠后的第一个字母大写:

    比如background-color写成backgroundColor

  2. 属性值都是字符串,设置时必须包括单位:

    比如,div.style.width的值不能写为100,而要写为100px

<body>
    <div id="d1" style="width:400px;height: 200px;border: 1px solid red"></div>
</body>
<script>
    var d1 = document.querySelector('#d1');
    d1.onclick = function(){
        //赋值则是设置
        d1.style.backgroundColor = 'red';
        //不赋值则是获取
        alert(d1.style.width);
    }
</script>

以上代码中,我们获取的CSS样式,均是行内样式;

如果将 样式表写在 style 标签内,我们将无法获取和修改;

getComputedStyle()
接受一个节点对象,返回该节点对象最终样式信息的对象,所谓“最终样式信息”,指的是各种CSS规则叠加后的结果。

注意: getComputedStyle() 是window对象下的方法,不是DOM对象

<style>
    #d1{
        width: 200px;height: 200px;
        border: 1px solid red;
    }
</style>

<body>
    <div id="d1" ></div>
</body>

<script>
    var d1 = document.querySelector('#d1');
    d1.onclick = function(){
        //获取不到
        console.log(d1.style.width);
        //获取计算后的样式
        console.log(getComputedStyle(d1).width);
    }
</script>

点击变大小案例:

<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
    #d1{
        width: 200px;height: 200px;
        border: 1px solid red;
    }
</style>
</head>
<body>
    <div id="d1" ></div>
</body>
<script>
    var d1 = document.querySelector('#d1');
    d1.onclick = function(){
        var w = parseInt(getComputedStyle(d1).width);
        var h = parseInt(getComputedStyle(d1).height);
        d1.style.width = w+10+'px';
		d1.style.height = h+10+'px';
    }
</script>

其他方法和属性:

document.documentURI 返回文档的 URL。

node.replaceChild(newChild, oldChild) 用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点。

node.insertBefore() : parentElement.insertBefore(newElement,referenceElement);

3.5 案例(节点属性)

网页开关灯效果实现(类名操作)

<style>
    .cls {
      background-color: black;
    }
  </style>
</head>
<body>
<input type="button" value="开/关灯" id="btn"/>

<script>
  document.getElementById("btn").onclick = function () {
    //document.body.className="cls";
//console.log(document.body.className);
    //判断body标签是否应用了cls类样式,同时设置body标签的类样式
    document.body.className = document.body.className == "cls" ? "" : "cls";
  };
</script>

点击按钮显示一个图片

<body>
<input type="button" value="显示图片" id="btn"/>
<img src="" alt="美女" id="im" width="300" height="400" />
<script>
  //根据id获取按钮,注册点击事件,添加事件处理函数
  document.getElementById("btn").onclick=function () {
    //根据id获取图片标签,设置src属性即可
    var imgObj=document.getElementById("im");
    //设置路径src属性
    imgObj.src="images/liuyan.jpg";
  };
</script>
</body>

案例点击按钮修改p标签内容

<body>
<input type="button" value="设置p的内容" id="btn"/>
<p id="p1">这是一个p</p>
<script>
  //点击按钮,设置p的内容
  //根据id获取按钮,注册点击事件,添加事件处理函数
  document.getElementById("btn").onclick = function () {
    //var pObj = document.getElementById("p1");
    document.getElementById("p1").innerText = "哦,这是p啊";
  };
</script>

</body>

点击按钮设置a标签的地址和热点文字

<input type="button" value="显示效果" id="btn"/>
<a href="http://www.baidu.com" id="ak">百度</a>
<script>
  //案例:点击按钮修改a的地址和热点文字
  //根据id获取按钮,注册点击事件,添加事件处理函数
  document.getElementById("btn").onclick=function () {
    var aObj=document.getElementById("ak");
    aObj.href="http://www.itcast.cn";
    aObj.innerText="传智播客";
  };
</script>
</body>

点击按钮设置所有的p的内容

<body>
<input type="button" value="改变内容" id="btn"/>
<p>红烧榴莲</p>
<p>清蒸臭豆腐</p>
<p>油炸大蒜</p>
<p>爆炒助教</p>
<p>凉拌班主任</p>
<script>

  //document.getElementsByTagName("标签的名字");

  //点击按钮,修改所有的p的内容
  //根据id获取按钮,注册点击事件,添加事件处理函数
  document.getElementById("btn").onclick = function () {
    //获取所有的p标签---根据标签名字来获取---伪数组
    var pObjs = document.getElementsByTagName("p");
    //循环遍历这个伪数组
    for (var i = 0; i < pObjs.length; i++) {
      pObjs[i].innerText = "我们都是p";
    }
  };

</script>

</body>

点击按钮修改图片的alt和title

<body>
<input type="button" value="显示效果" id="btn"/>
<img id="im" src="images/cangjingkong.jpg" alt="" title=""/>
<script>
  //点击按钮,修改图片的宽和高,alt和title属性值
  //根据id获取按钮,注册点击事件,添加事件处理函数
  document.getElementById("btn").onclick = function () {
    //根据id获取图片标签
    var imgObj = document.getElementById("im");
    //设置属性
    imgObj.width = "500";
    imgObj.height = "600";
    imgObj.alt = "好漂亮";
    imgObj.title = "美女";
  };
</script>
</body>

点击按钮修改按钮的值

<body>
<input type="button" value="按钮" id="btn"/>
<script>
  //案例:点击按钮修改按钮的value属性值
  //根据id获取按钮,注册点击事件,添加事件处理函数
//  document.getElementById("btn").onclick=function () {
//    document.getElementById("btn").value="改变吧";
//  };

  //在某个元素的自己的事件中,this就是当前的这个元素

  document.getElementById("btn").onclick=function () {
    //当前对象
    this.value="改变吧";
  };
</script>

</body>

点击图片修改自身的宽和高

<body>
<img src="images/boduo.jpg" alt="" id="im" />
<script>
  //点击图片,修改自身的宽和高
  //根据id获取图片,注册点击事件,添加事件处理函数
  document.getElementById("im").onclick=function () {
    this.width="300";
    this.height="400";
  };
</script>

</body>

点击按钮修改所有的文本框的值

<body>
<input type="button" value="显示效果" id="btn"/><br/>
<input type="text" value=""/><br/>
<input type="text" value=""/><br/>
<input type="text" value=""/><br/>
<input type="text" value=""/><br/>
<input type="text" value=""/><br/>
<script>
  //根据id获取按钮,注册点击事件,添加事件处理函数
  document.getElementById("btn").onclick=function () {
    //根据标签名字获取文本框,所有的input标签
    var inputs=document.getElementsByTagName("input");
    for(var i=0;i<inputs.length;i++){
      //判断当前input是不是文本框
      if(inputs[i].type=="text"){
        inputs[i].value="我是文本框";
      }
    }

  };
</script>

排他功能

<body>
<input type="button" value="没怀孕"/>
<input type="button" value="没怀孕"/>
<input type="button" value="没怀孕"/>
<input type="button" value="没怀孕"/>
<input type="button" value="没怀孕"/>
<script>

  //获取所有的按钮
  var btnObjs = document.getElementsByTagName("input");
  //循环,为每个按钮注册点击事件,添加事件处理函数
  for (var i = 0; i < btnObjs.length; i++) {
    //每个按钮注册点击事件
    btnObjs[i].onclick = function () {
      //把所有的按钮的value值还原
      for (var j = 0; j < btnObjs.length; j++) {
        btnObjs[j].value = "没怀孕";
      }
      //设置当前的这个按钮的value
      this.value = "怀孕了";
    };
  }
</script>

点击按钮禁用文本框

<input type="button" value="禁用文本框" id="btn"/>
<input type="text" value="" id="txt"/>
<script src="common.js"></script>
<script>
  //点击按钮禁用这个文本框
 document.getElementById("btn").onclick = function () {
    document.getElementById("txt").disabled = true;
  };
</script>

鹦鹉学舌

<body>
    <input type="text" id="t1" > <br>
    <input type="text" id="t2" >
</body>
<script>
    document.getElementById('t1').oninput = function(){
        document.getElementById('t2').value = this.value;
    }
</script>

全选和全不选

<style>
    table {
        border-collapse: collapse;
        border-spacing: 0;
        border: 1px solid #c0c0c0;
        width: 500px;
    }

    th,
    td {
        border: 1px solid #d0d0d0;
        color: #404060;
        padding: 10px;
    }
</style>

<body>
    <table>
        <thead>
            <tr>
                <th>
                    <input type="checkbox" id="th" />
                </th>
                <th>菜名</th>
                <th>饭店</th>
            </tr>
        </thead>
        <tbody id="tb">
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>红烧肉</td>
                <td>田老师</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>西红柿鸡蛋</td>
                <td>田老师</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>油炸榴莲</td>
                <td>田老师</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>清蒸助教</td>
                <td>田老师</td>
            </tr>
        </tbody>
    </table>
</body>
<script>
    document.getElementById('th').onclick = function () {
        var tb = document.getElementsByTagName('input');
        if (this.checked == true) {
            // console.log(tb);
            for (var i = 0; i < tb.length; i++) {
                tb[i].checked = true;
            }
        } else {
            for (var i = 0; i < tb.length; i++) {
                tb[i].checked = false;
            }
        }
    }
</script>

作业,实现反选

表格鼠标悬浮高亮(接上一个案例)

var t = document.getElementsByTagName('tbody')[0];
t.onmouseover = function(e){
    e.target.parentElement.style.background = '#F5F5F5';
}
t.onmouseout = function(e){
    e.target.parentElement.style.background = '#fff';
}

3.6 案例(样式操作)

节点方式隔行变色

<body>
    <input type="button" value="隔行变色" id="btn" />
    <ul id="uu">
        <li>雪花啤酒</li>
        <li>金士百啤酒</li>
        <li>青岛啤酒</li>
        <li>燕京啤酒</li>
        <li>百威啤酒</li>
        <li>哈尔滨啤酒</li>
        <li>乐宝啤酒</li>
        <li>崂山啤酒</li>
    </ul>
</body>
<script>
    //点击按钮,所有的li隔行变色---奇红偶黄
    document.getElementById("btn").onclick = function () {
        var count = 0;
        //要获取ul中所有的子节点
        var nodes = document.getElementById("uu").childNodes;
        for (var i = 0; i < nodes.length; i++) {
            var node = nodes[i];
            //判断这个节点是不是li
            if (node.nodeType == "1" && node.nodeName == "LI") {
                node.style.backgroundColor = count % 2 == 0 ? "red" : "yellow";
                count++;//记录li标签的个数
            }
        }
    };
</script>

验证密码的长度改变背景颜色

<input type="text" value="" id="txt"/>
<script>
  //根据id获取文本框---失去焦点的事件
  document.getElementById("txt").onblur=function () {
    //判断文本框中输入的内容长度是否在6到10个之间,如果是这样的,则背景颜色为绿色
    if(this.value.length>=6&&this.value.length<=10){
      this.style.backgroundColor="green";
    }else{
      this.style.backgroundColor="red";
    }
  };
</script>

div的高亮显示

<style>
    div {
        width: 200px;
        height: 200px;
        background-color: green;
        float: left;
        margin-right: 20px;
        cursor: pointer;
        border: 2px solid green;
    }
</style>

<body>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>

    <script>
        //根据标签名字获取所有的div
        var divObjs = document.getElementsByTagName("div");
        //循环遍历
        for (var i = 0; i < divObjs.length; i++) {
            //为每个div添加鼠标进入事件
            divObjs[i].onmouseover = mouseoverHandle;
            //为每个div添加鼠标离开事件
            divObjs[i].onmouseout = mouseoutHandle;
        }
        function mouseoverHandle() {
            this.style.border = "2px solid red";
        }
        function mouseoutHandle() {
            //希望这个样式属性的值还原成默认的时候,值就是""空的字符串
            this.style.border = "";
        }
    </script>

鼠标点哪图片飞到哪里

思路:给整个dom绑定鼠标点击事件,获取点击位置后修改图片位置

<style>
    img {
        position: absolute;
        width: 50px;
        height: 50px;
    }
</style>

<body>
    <img src="/img/c3.jpg" alt="">
</body>
<script>
    var im = document.getElementsByTagName('img')[0];
    document.onclick = function (e) {
        im.style.left = e.clientX + 'px';
        im.style.top = e.clientY + 'px';
    }
</script>

跟着鼠标飞的天使

思路:点击图片后,给整个dom绑定鼠标移动事件,让图片跟随

<style>
    img {
        position: absolute;
        width: 50px;
        height: 50px;
    }
</style>

<body>
    <img src="/img/c3.jpg" alt="">
</body>
<script>
    var im = document.getElementsByTagName('img')[0];
    im.onclick = function () {
        document.onmousemove = function (e) {
            im.style.left = e.clientX + 'px';
            im.style.top = e.clientY + 'px';
        }
    }
</script>

实时获取鼠标在div内的坐标

<body>
    <div id="div3">3
       <p id="p"></p>
    </div>

</body>
<script>
    var p = document.getElementById('p');
    document.getElementById('div3').onmousemove = function(e){
        p.innerHTML = e.clientX+','+e.clientY;
        p.style.top = e.clientY+"px";
        p.style.left = e.clientX+"px";
    }
</script>

点击按钮设置div的宽和高及背景颜色

<head>
  <meta charset="UTF-8">
  <title>title</title>
  <style>
    div{
      width: 100px;
      height: 50px;
      background-color: yellow;
    }
  </style>
</head>
<body>
<input type="button" value="显示效果" id="btn"/>
<div id="dv"></div>
<script>

  //点击按钮,设置div的宽和高,及背景颜色
  //根据id获取按钮,注册点击事件,添加事件处理函数
  document.getElementById("btn").onclick=function () {
    //获取div
    var dvObj=document.getElementById("dv");
    dvObj.style.width="300px";
    dvObj.style.height="200px";
    //css中的属性如果是多个单词连接的,在js代码DOM操作中多个单词中间的-干掉,后面单词的首字母变大写
    dvObj.style.backgroundColor="pink";
  };

</script>

点击按钮隐藏div

  <style>
    div{
      width: 200px;
      height: 100px;
      background-color: orangered;
    }
  </style>
</head>
<body>
<input type="button" value="隐藏" id="btn"/>
<input type="button" value="显示" id="btn2"/>
<div id="dv"></div>
<script src="common.js"></script>
<script>
  //点击按钮隐藏div
  document.getElementById("btn").onclick=function () {
    //获取div,隐藏
    document.getElementById("dv").style.display="none";
  };
  document.getElementById("btn2").onclick=function () {
    document.getElementById("dv").style.display="block";
  };
</script>

点击按钮改变列表的背景颜色

<input type="button" value="改变颜色" id="btn"/>
<ul id="uu">
  <li>乔峰</li>
  <li>卡卡西</li>
  <li>佐助</li>
  <li>自来也</li>
  <li>纲手</li>
  <li>雏田</li>
  <li>露琪亚</li>
</ul>
<script src="common.js"></script>
<script>
  //获取按钮,注册点击事件,添加事件处理函数
  document.getElementById("btn").onclick=function () {
    document.getElementById("uu").style.backgroundColor="pink";
  };
</script>

点击按钮列表隔行变色

<input type="button" value="隔行变色" id="btn"/>
<ul id="uu">
  <li>五菱宏光</li>
  <li>路虎</li>
  <li>兰博基尼</li>
  <li>布加迪威龙</li>
  <li>玛莎拉蒂</li>
  <li>奥拓</li>
  <li>拖拉机</li>
  <li>桑塔纳</li>
</ul>
<script>
  //点击按钮,li隔行变色:奇红偶黄
  //获取按钮,添加点击事件
  document.getElementById("btn").onclick = function () {
    //获取id为uu的ul中所有的li
    var list = getElementsByTagName("li");
    //遍历
    for (var i = 0; i < list.length; i++) {
//      if (i % 2 == 0) {
//        list[i].style.backgroundColor = "red";
//      } else {
//        list[i].style.backgroundColor = "yellow";
//      }

      list[i].style.backgroundColor = i % 2 == 0 ? "red" : "yellow";
    }
  };
</script>

3.7 案例(节点操作)

动态可编辑表格

<style>
    table {
        border-collapse: collapse;
        border-spacing: 0;
        border: 1px solid #c0c0c0;
        width: 500px;
    }

    th,
    td {
        border: 1px solid #d0d0d0;
        color: #404060;
        padding: 10px;
    }
</style>

<body>
    <input type="button" value="添加一行" id="addrow">
    <table>
        <thead>
            <tr>
                <td>菜名</td>
                <td>饭店</td>
                <td>厨师</td>
            </tr>
        </thead>
        <tbody id="tb"></tbody>
    </table>
</body>
<script>
    var tbs = document.getElementsByTagName('table')[0];
    tbs.onclick = function (e) {
        var clicks = e.target;
        if (clicks.nodeName == 'TD') {
            // var inp = document.createElement('input');
            // inp.value = clicks.innerText;
            // console.log(clicks.parentElement);
            clicks.innerHTML = '<input value=' + clicks.innerText + '>';
            tbs.getElementsByTagName('input')[0].onblur = function () {
                clicks.innerHTML = this.value;
            }
        }
    }

    var addrow = document.getElementById('addrow');
    addrow.onclick = function(){
        var tr = document.createElement('tr');
        for(var i = 0; i<3;i++){
            tr.appendChild(document.createElement('td'));
        }
        document.getElementById('tb').appendChild(tr);
    }

</script>

无刷新评论

<body>
    <div id="cont">
        <div>
            <p>name:</p>
            <p>我是评论内容</p>
            <hr>
        </div>
    </div>

    <div>
        昵称:
        <input type="text" value="" id="userName" /><br/><br/>
        <textarea name="" id="tt" cols="103" rows="10"></textarea><br/>
        <input type="button" value="评论一下" id="btn" /><br/>
    </div>
</body>
<script>
    var un = document.getElementById('userName');
    var tt = document.getElementById('tt');

    document.getElementById('btn').onclick = function(){
        var d = document.createElement('div');
        d.innerHTML = '<p>'+un.value+':</p>';
        d.innerHTML += '<p>'+tt.value+'</p>';
        d.innerHTML += '<hr>';
        document.getElementById('cont').appendChild(d);
        un.value = '';
        tt.value = '';
    }

</script>

第4章 事件对象

4.1 概述

事件的触发,大部分情况下是用户的一种行为,也就是说,我们并不能确定用户什么时间触发;

而且,由于事件的传播机制,我们甚至不能确定事件具体触发在哪个节点;这是一件很不爽的事情;

如何解决呢?

事件发生以后,系统会调用我们写好的事件处理程序

系统会在调用处理程序时,将事件发生时有关事件的一切信息,封装成一个对象,

作为参数传给监听函数(事件处理程序),我们把这个对象称为 事件对象
有关事件发生的一切信息,都包含在这个事件对象中;

根据事件类型的不同,事件对象中包含的信息也有所不同;
如点击事件中,包含鼠标点击的横纵坐标位置,键盘事件中,包含键盘的键值等;

<body>
    <div id="div">
        <p>pppp</p>
    </div>
    <input type="text" value="" id="i">
</body>
<script>
var d = document.getElementById('div');
//鼠标事件
d.addEventListener('click',function(e){
    console.log(e);
});

var i = document.getElementById('i');
//键盘事件
i.addEventListener('keydown',k);
function k(e){
    console.log(e);
}
</script>

20180528-183455

4.2 事件对象中的常用属性及方法

4.2.1属性

event.bubbles:属性返回一个布尔值,表示当前事件是否会冒泡;
event.eventPhase:返回一个整数值,表示事件流在传播阶段的位置

0:事件目前没有发生。
1:事件目前处于捕获阶段。
2:事件到达目标节点。
3:事件处于冒泡阶段。

event.type:返回一个字符串,表示事件类型,大小写敏感;
event.timeStamp:返回一个毫秒时间戳,表示事件发生的时间;

clientX、clientY :获取鼠标事件触发的坐标

<body>
    <div id="d">
        <p id="p">sdf</p>
    </div>
</body>
<script>
    var p = document.getElementById('p');
    p.onclick = function(e){
        //当前事件是否会冒泡
        console.log(e.bubbles);
        //事件目前所处的节点
        console.log(e.eventPhase);
        //事件类型
        console.log(e.type);
        //事件发生的时间戳
        console.log(e.timeStamp);
    }
</script>

4.2.2 事件代理/委托

event.target:对事件起源目标的引用,属性返回触发事件的那个节点。
event.currentTarget:属性返回事件当前所在的节点,即正在执行的监听函数所绑定的那个节点。
作为比较,target属性返回事件发生的节点。

var d = document.getElementById('d');
d.onclick = function(e){
    //返回事件节点
    console.log(e.currentTarget);
    //返回触发节点
    console.log(e.target);
}

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父
节点上,由父节点的监听函数统一处理多个子元素的事件。
这种方法叫做事件的代理也叫 事件委托 也有人称为 事件代理

<head>
    <title></title>
    <meta charset="UTF-8">
    <style>
        div{padding: 40px}
        #div3{width: 300px;height: 300px;border: 1px solid red;}
        #div2{width: 200px;height: 200px;border: 1px solid red;}
        #div1{width: 100px;height: 100px;border: 1px solid red}
    </style>
</head>
<body>
    <div id="div3">3
        <div id="div2">2
            <div id="div1">1</div>
        </div>
    </div>
</body>
<script>
    var d = document.getElementById('div3');
    d.onclick = function(e){
        e.target.style.background = 'red';
    }
</script>

4.3.3 阻止浏览器默认行为&阻止事件传播

event.preventDefault()
方法取消浏览器对当前事件的默认行为,
比如点击链接后,浏览器跳转到指定页面,或者按一下空格键,页面向下滚动一段距离。

event.stopPropagation()
方法阻止事件在DOM中继续传播,防止再触发定义在别的节点上的监听函数

<body>
    <div id="div2">2
        <div id="div1">1
            <a id="a" href="http://qq.com">王者喝农药</a>
        </div>
    </div>
</body>
<script>
    var d2 = document.getElementById('div2');
    var d1 = document.getElementById('div1');
    var a = document.getElementById('a');
    d2.onclick = function(e){
       alert('d2');
    }
    d1.onclick = function(e){
       alert('d1');
    }
    a.onclick = function(e){
        //阻止事件传播
        // e.stopPropagation();
       alert('a');
       //阻止浏览器默认行为
       e.preventDefault();
    }
</script>

4.3 案例

阻止超链接默认跳转

<body>
<!--第1种写法-->
<a href="http://www.baidu.com" onclick="alert('哈哈'); return false;">百度</a>


<!--第2种写法-->

<script>
  function f1() {
    alert("嘎嘎");
    return false;
  }
</script>
<a href="http://www.baidu.com" onclick="return f1();">百度</a>

<!--第3种写法-->
<a href="http://www.baidu.com" id="ak">百度</a>
<script>
  document.getElementById("ak").onclick=function () {
    alert("哈哈");
    return false;
  };
</script>

点击小图显示大图

<body>
<a id="ak" href="images/1.jpg"><img src="images/1-small.jpg" alt="" id="im"></a>
<script>
  //点击小图片,显示大图---修改了这个图片标签的src的属性值
  //根据id获取小图,注册点击事件,添加事件处理函数
  document.getElementById("im").onclick=function () {
    //根据id获取超链接
    var aObj=document.getElementById("ak");
    this.src=aObj.href;
    //阻止超链接的默认跳转事件
    return false;
  };
</script>

第5章 浏览器对象模型

5.1 介绍

浏览器对象模型(Browser Object Model)--英文简称 BOM,浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。我们使用JavaScript与浏览器交互的所有内容,均来自 浏览器对象模型

浏览器对象模型的具体实例化对象就是 window 对象;

window 对象下有很多属性和方法,我们前面学过的DOM对象,就是window对象的一个属性,只不过这个属性的值又是一个对象,因此也成为window对象的子对象;

https://developer.mozilla.org/zh-CN/docs/Web/API/Window

5.2 对话框

window.alert() : 显示一个警告对话框,上面显示有指定的文本内容以及一个"确定"按钮。

window.prompt() : 显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字.

var s = window.prompt('你觉得很幸运吗?','是的');
console.log(s);

window.confirm() :方法显示一个具有一个可选消息和两个按钮(确定和取消)的模态对话框 。

5.3 页面加载事件

onload

window.onload = function () {
  // 当页面加载完成执行
  // 当页面完全加载所有内容(包括图像、脚本文件、CSS 文件等)执行
}

5.4 浏览器控制台

window.console : 返回console对象的引用,该对象提供了对浏览器调试控制台的访问。

Console.clear() : 清空控制台。

Console.error() : 打印一条错误信息

Console.table() : 将数组或对象数据在控制台以表格形式打印

Console.log() : 打印字符串,使用方法比较类似C的printf、PHP的echo等格式输出

5.5 定时器

setTimeout()和clearTimeout()

在指定的毫秒数到达之后执行指定的函数,只执行一次

// 创建一个定时器,1000毫秒后执行,返回定时器的标示
var timerId = window.setTimeout(function () {
  console.log('Hello World');
}, 1000);

// 取消定时器的执行
window.clearTimeout(timerId);

setInterval()和clearInterval()

定时调用的函数,可以按照给定的时间(单位毫秒)周期调用函数

// 创建一个定时器,每隔1秒调用一次
var timerId = window.setInterval(function () {
  var date = new Date();
  console.log(date.toLocaleTimeString());
}, 1000);

window.clearInterval(timerId);

5.6 案例

一起来摇摆

<style>
    #div{
        position: absolute;
    }
</style>
<body>
    <input type="button" value="摇起来" id="btn1">
    <div id="div">
        <img src="/img/c2.jpg" style="width: 50px;height: 50px;" alt="">
        <img src="/img/c3.jpg" style="width: 50px;height: 50px;" alt="">
    </div>
</body>
<script>
    var b1 = document.getElementById('btn1');
    var b2 = document.getElementById('btn2');

    b1.onclick = function(){
        
        if(this.value != '停止'){
            this.value = '停止';
            var d = document.getElementById('div');
            c = window.setInterval(function(){
                d.style.left = parseInt(Math.random() * 100 +1) + 'px'
                d.style.top = parseInt(Math.random() * 100 +1) + 'px'
            },50);
        }else{
            this.value = '摇起来';
            clearInterval(c);
        }
    }
</script>   

眼看着图片就这个飞走了

<style>
    #div{
        position: absolute;
    }
</style>
<body>
    <input type="button" value="摇起来" id="btn1">
    <div id="div">
        <img src="/img/c2.jpg" style="width: 50px;height: 50px;" alt="">
    </div>
</body>
<script>
    var b1 = document.getElementById('btn1');
    b1.onclick = function(){
        var d = document.getElementById('div');
        window.setInterval(function(){
            var s = parseInt(getComputedStyle(d)['top']);
            var l = parseInt(getComputedStyle(d)['left']);
            // console.log(l);
            d.style.top = s-1+'px';
            d.style.left = l+5+'px';
        },50)
    }
</script> 

5.7 location对象

https://developer.mozilla.org/zh-CN/docs/Web/API/Location

window.location 只读属性,返回一个  Location对象,其中包含有关文档当前位置的信息;

URL

统一资源定位符 (Uniform Resource Locator, URL)

URL的组成:

scheme://host:port/path?query#fragment
scheme:通信协议
	常用的http,ftp,maito等
host:主机
	服务器(计算机)域名系统 (DNS) 主机名或 IP 地址。
port:端口号
	整数,可选,省略时使用方案的默认端口,如http的默认端口为80。
path:路径
	由零或多个'/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。
query:查询
	可选,用于给动态网页传递参数,可有多个参数,用'&'符号隔开,每个参数的名和值用'='符号隔开。例如:name=zs
fragment:信息片断
	字符串,锚点.

console.log(location);

20180601-211004

页面跳转

location.href = 'http://qq.com'

5.8 history对象

https://developer.mozilla.org/zh-CN/docs/Web/API/History

history.back() : 前往上一页, 用户可点击浏览器左上角的返回按钮模拟此方法

history.forward() : 在浏览器历史记录里前往下一页,用户可点击浏览器左上角的前进按钮模拟此方法

history.go() : 通过当前页面的相对位置从浏览器历史记录( 会话记录 )加载页面。比如:参数为-1的时候为上一页,参数为1的时候为下一页.

5.9 navigator对象

https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator

userAgent : 通过userAgent可以判断用户浏览器的类型

platform : 通过platform可以判断浏览器所在的系统平台类型.

geolocation : 位置定位对象;

参考: https://developer.mozilla.org/zh-CN/docs/Web/Reference/API

posted on 2024-01-07 03:05  xirang熙攘  阅读(6)  评论(0编辑  收藏  举报