2. JavaScript基础&实战&高级

文章目录

  • 一、ECMAScript
    • 1. 编写位置
      • 1.1 script标签里
      • 1.2 标签的属性里
        • onclick属性中
        • href属性中
      • 1.3 外部js文件里
    • 2. 基本语法
      • 2.1 注释
      • 2.2 规则
      • 2.3 字面量
      • 2.4 变量
      • 2.5 标识符
      • 2.6 数据类型
        • String 字符串
        • Number 数值
        • Boolean 布尔值
        • Null 空值
        • Undefined 未定义
        • Object 对象(引用数据类型)
      • 2.7 强制类型转换
        • 转换成String
        • 转换成Number
        • 转换成Boolean
      • 2.8 其他进制的数字
      • 2.9 运算符
        • 算数运算符
        • 一元运算符
        • 自增和自减
        • 逻辑运算符
        • 非布尔值的与或运算
        • 赋值运算符
        • 关系运算符
        • Unicode编码表
        • 相等运算符
        • 条件运算符
        • 运算符的优先级
    • 3. 流程控制语句
      • 3.1 if语句
      • 3.2 switch…case…语句
      • 3.3 while语句
      • 3.4 for循环
      • 3.5 break和continue
        • break
        • continue
        • 测试程序性能
    • 4. 对象
      • 4.1 对象的分类
        • 内建对象
        • 宿主对象
        • 自定义对象
      • 4.2 操作对象
      • 4.3 对象属性名的其他表示方式
      • 4.4 基本数据类型和引用数据类型
        • 基本数据类型
        • 引用数据类型
        • 区别
      • 4.5 对象字面量
      • 4.6 枚举对象中的属性
    • 5.函数
      • 5.1 创建函数
        • 声明法
        • 函数表达式法
        • 立即执行函数
      • 5.2 函数特性
      • 5.3 作用域
        • 全局作用域
        • 函数作用域
      • 5.4 debug
      • 5.5 this
      • 5.6 使用工厂方法创建对象
        • 问题:
      • 5.7 构造函数
        • 解决方法:
        • 构造函数的执行流程
        • 问题:
      • 5.8 原型prototype
        • tostring
      • 5.9 垃圾回收(GC)
      • 5.10 函数的方法
        • call()和apply()
      • 5.11 arguments
      • 5.12 包装类
    • 6. 内建对象
      • 6.1 数组
        • 对象法创建数组
        • 字面量法创建数组
        • 数组的方法
        • `push()`
        • `pop()`
        • `unshift()`
        • `shift()`
        • `slice()`
        • `splice()`
        • `concat()`
        • `join()`
        • `reverse()`
        • `sort()`
        • 遍历数组
        • for循环
        • forEach()
      • 6.2 Date
        • getDate()
        • getDay()
        • getMonth()
        • getFullYear()
        • getTime()
      • 6.3 Math
      • 6.4 String
        • 属性
        • `length`
        • 方法
        • `charAt()`
        • `charCodeAt()`
        • `fromCharCode()`
        • `concat()`
        • `indexOf()`
        • `lastIndexOf()`
        • `slice()`
        • `substring()`
        • `split()`
        • `toUpperCase()`
        • `toLowerCase()`
    • 7. 正则表达式
      • 7.1 创建正则表达式的对象
      • 7.2 使用字面量来创建正则表达式
      • 7.3 字符串和正则相关的方法
        • `split()`
        • `search()`
        • `match()`
        • `replace()`
  • 二、DOM
    • 1. DOM简介
      • 1.1 DOM
      • 1.2 节点Node
      • 1.3 事件
        • 直接在标签里绑定事件
        • 为对象绑定事件
    • 2. DOM查询
      • 2.1 获取元素节点
        • 通过document对象调用
        • 获取元素内部HTML代码
        • 读取元素节点属性
      • 2.2 获取元素节点的子节点
        • 通过具体的元素节点调用
      • 2.3 获取父节点和兄弟节点
        • 通过具体的元素节点调用
      • 2.3 选择器
        • document.querySelector()
        • document.querySelectorAll()
    • 3. DOM增删改
      • 3.1 为一个节点添加一个子节点
      • 3.2 在一个节点前面插入一个节点
      • 3.3 替换节点
      • 3.4 删除节点
    • 4. DOM修改样式
      • 4.1 改元素内联样式
      • 4.2 获取元素样式
        • 获取元素的内联样式(可改)
        • 获取元素正在显示的样式(只读)
      • 4.3 其他样式相关属性
        • clientWidth clientHeight
        • offsetWidth offsetHeight
        • offsetParent
        • offsetLeft offsetTop
        • scrollWidth scrollHeight
        • scrollLeft scrollTop
    • 5. 事件
      • 5.1 事件对象
        • onscroll事件
        • onmousemove事件
        • clientX clientY 事件对象的属性
        • pageX pageY
        • div跟随鼠标移动
      • 5.2 事件的冒泡
        • 事件的委派
      • 5.3 事件的绑定
        • addEventListener()
        • attachEvent()
        • 解决兼容
        • 拖拽box1元素
        • 滚轮的事件
        • 键盘事件
  • 三、BOM
    • 1. BOM对象
      • 1.1 Window
      • 1.2 Navigator
      • 1.3 Location
      • 1.4 History
      • 1.5 Screen
    • 2. 定时器
      • 2.1 定时调用
      • 2.2 延时调用
        • 切换图片练习
    • 3. 类的操作
    • 4. JSON
      • 4.1 JSON简介
      • 4.2 JSON分类
        • 对象{}
        • 数组[]
      • 4.3 JSON中允许的值
      • 4.4 将JSON字符串转换为JS对象
      • 4.5 将JS对象转换为JSON字符串
      • 4.7 解决JSON在IE7及以下无效的情况
      • 4.8 终极解决办法

  • JavaScript包含三部分
    • ECMAScript:语法标准
    • DOM:操作文档
    • BOM:操作浏览器

一、ECMAScript

1. 编写位置

1.1 script标签里

<script type="text/javascript">
	alert("Hello world!");      //控制浏览器弹出一个警告框
	document.write("Hello world!"); //让计算机在页面中输出一个内容
	console.log("Hello world!");  //向控制台输出一个内容
	var score=+prompt("请输入小明的期末成绩:") //弹出一个带有文本框的提示框 
script>
  • prompt()函数的返回值是string类型,如果需要转换成数值型,则+prompt()

1.2 标签的属性里

onclick属性中

<button onclick="alert('Hello world!');">点我button>

href属性中

<a href="javascript:alert('Hello world!');">点我a>
<a href="javascript:;">a> //设置超链接不跳转
  • 写在标签的属性里属于结构与行为耦合,不方便维护,不推荐使用。

1.3 外部js文件里

<script type="text/javascript" src="js/script.js">script>
<script type="text/javascript">
	alert("我是内部的JS代码")script>
  • 写到外部文件中可以在不同的页面中同时引用,也可以利用到浏览器的缓存机制,推荐使用。
  • script标签一旦用于引入外部文件,就不能再编写代码了,即使编写了浏览器也会忽略。
  • 如果需要则可以再创建一个新的script标签用于编写内部代码。

2. 基本语法

2.1 注释

//单行注释

/*
 *多行注释
 */

2.2 规则

  • JS中严格区分大小写
  • JS中每条语句都以;结尾
  • JS中会忽略多个空格和换行,可以利用这个对代码进行格式化

2.3 字面量

  • 常量,不可改变

2.4 变量

  • 声明变量并赋值
var a=4;

2.5 标识符

  • 在JS中所有的可以由我们自主命名的都可以称为是标识符
  • 例如:变量名、函数名、属性名都属于标识符
  • 命名标识符时要遵守如下规则:
    • 标识符中可以含有字母、数字、_ 、&
    • 标识符不能以数字开头
    • 标识符不能是ES中的关键字或保留字
    • 标识符一般采用驼峰命名法
      • 首字母小写,每个单词的开头字母大写,其余字母小写
      • xxxYyyZzz
        2. JavaScript基础&实战&高级_第1张图片

2.6 数据类型

  • 数据类型:字面量的类型
  • JS中共有6种数据类型

String 字符串

  • 需要使用引号引起来
  • 单引号双引号都可以,但是不能混用
  • 引号嵌套时,外面双引号里面单引号,或者外面单引号里面双引号
  • 转义字符:表示一些特殊符号
    • \"表示"
    • \'表示'
    • \n表示换行
    • \t制表符
    • \\表示\

Number 数值

  • 包括整数和浮点数
  • 整数的运算基本可以保证精确
  • 浮点数运算可能得到一个不精确的结果,千万不要使用JS进行高精度要求的运算
  • Number.MAX_VALUE:表示数字的最大值1.7976931348623157e+308
    • 如果使用Number表示数字超过了最大值,则会返回一个Infinity表示正无穷
    • Infinity:一种特殊数字,正无穷
    • -Infinity:一种特殊数字,负无穷
  • Number.MIN_VALUE:表示大于0的最小值5e-324
  • NaN:一种特殊数字,Not a Number
  • typeof 变量检查一个变量的类型
    • 检查字符串时,返回string
    • 检查数值时,返回number
    • 检查以上几种特殊数字时,返回的都是number

Boolean 布尔值

  • true 表示真
  • false 表示假
  • 使用typeof检查一个布尔值时,返回boolean
    var bool = false;

Null 空值

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

Undefined 未定义

  • 值只有一个,就是undefined
  • 当声明一个变量但是并不给变量赋值时,值就是undefined
  • 使用typeof检查一个undefined时会返回undefined;

Object 对象(引用数据类型)

2.7 强制类型转换

  • 将其他数据类型转换为String Number Boolean

转换成String

  • 方法一
    • 调用toString()方法
    • 该方法不会影响到原变量,它会将转换的结果返回
    • 但是Null和undefined这两个值没有toString()方法,如果调用会报错
a=a.toString();
  • 方法二:
    • 调用String()函数,并将被转换的数据作为参数传递给函数
    • 对于number和boolean实际上就是调用toString()方法
    • 但对于null和undefined就不会调用tostring()方法
a=String(a);

转换成Number

  • 方法一:
    • 使用Number()函数
    • 字符串–>数字
      • 如果是纯数字的字符串,则直接将其转换为数字
      • 如果字符串中有非数字的内容,则转换为NaN
      • 如果字符串是一个空串或者是一个全是空格的字符串,则直接将其转换为0
    • 布尔–>数字
      • true 转成1
      • false 转成0
    • null–>数字 0
    • undefined–>数字NaN
a=Number(a);
  • 方法二:
    • 这种方式专门用来对付字符串
    • parseInt()把一个字符串转换为一个整数,从左向右扫描,一旦发现一个非数字的内容则停止扫描
    • parseFloat()把一个字符串转换为一个浮点数
    • 如果对非String使用parseInt()或parseFloat(),它会先将其转换为String然后再操作
a=parseInt(a);
b=parseFloat(b);

转换成Boolean

  • 使用Boolean()函数
  • 数字–>布尔
    • 除了0和NaN,其余都是true
  • 字符串–>布尔
    • 除了空串,其余都是true
  • null和undefined都会转换为false

2.8 其他进制的数字

  • 16进制的数字:0x开头
  • 8进制的数字:0开头
  • 2进制的数字:0b开头,但不是所有的浏览器都支持
  • “070”这种字符串,有些浏览器会当成8进制解析,有些会当成10进制解析
  • 可以在parseInt()中传递一个第二个参数,来指定数字的进制
a=parseInt(a,10);

2.9 运算符

  • 通过运算符可以对一个或多个值进行运算,并获取运算结果
  • 比如:typeof就是运算符,可以来获得一个值的类型,它会将该值的类型以字符串的形式返回

算数运算符

  • 当对非Number类型的值进行运算时,会将这些值转换为Number(+中含字符串除外)
    • 可以通过为一个值-0 *1 /1来将其转换为Number
  • 任何值和NaN做运算都得NaN
  • +
    • 如果对两个字符串进行加法运算,则会做拼串
    • 任何的值和字符串做加法,都会先转换为字符串,然后再拼接
      • 可以利用这个特性,将一个任意的数据类型转换为String
      • c= c+"";
      • 这是一种隐式的类型转换,由浏览器自动完成,实际上它也是调用String()
  • - 减法
  • * 乘法
  • / 除法
  • % 取余数

一元运算符

  • 只需要一个操作数
  • + 正号:不会对数字产生任何影响
  • - 负号:可以对数字进行负号的取反
  • 对于非Number类型的值
    • 会现将其转换为Number,然后再运算
    • 可以对一个其他数据类型使用+,将其转换为number,原理和Number()函数一样
    • a=+a;

自增和自减

  • 自增++
    • 分为两种a++++a
    • 两种都会立即使原变量的值自增1
    • 不同的是a++++a的值不同
      • a++:等于自增前的值
      • ++a:等于新值
  • 自减–
    • 分为两种a----a
    • 两种都会立即使原变量的值自减1
    • 不同的是a----a的值不同
      • a--:等于自减前的值
      • --a:等于新值

逻辑运算符

  • !
    • 对一个布尔值进行取反操作,true变false,false变true
    • 如果对一个值进行两次取反,它不会变
    • 如果对一个非布尔值进行取反,则会先将其转换为布尔值,再取反
    • 可以为一个任意数据类型取两次反!!a,来将其转换为布尔值,原理和Boolean()函数一样
  • &&
    • 两个值中只要有一个值为false就返回false,只有两个值都为true时,才会返回true
    • 是短路的与:如果第一个值为false,则不会看第二个值
  • ||
    • 两个值中只要有一个值为true就返回true,只有两个值都为false时,才会返回false
    • 是短路的或:如果第一个值为true,则不会看第二个值

非布尔值的与或运算

  • 对于非布尔值进行与或运算时,会现将其转换为布尔值,然后再运算,并返回原值
  • 与运算:
    • 如果第一个值为true,则必然返回第二个值
    • 如果第一个值为false,则直接返回第一个值
  • 或运算:
    • 如果第一个值为true,则直接返回第一个值
    • 如果第一个值为false,则返回第二个值

赋值运算符

  • a+=5;
  • a-=5;
  • a*=5;
  • a/=5;
  • a%=5;

关系运算符

  • >
  • >=
  • <
  • <=
  • 对于非数值进行比较时,会将其转换为数字然后再比较
  • 任何值和NaN做任何比较都是false
  • 比较两个字符串时,比较的是字符串的字符编码
  • 比较字符编码时是一位一位进行比较
  • 如果两位一样,则比较下一位,所以借用它对英文进行排序
  • 如果比较两个字符串型的数字时,一定要转型,前面加个+

Unicode编码表

  • 在Js的字符串中使用Unicode编码
    • \U四位编码
    • console.log("\u2620");
  • 在网页中使用
    • &#编码;这里的编码需要的是十进制

相等运算符

  • ==相等
    • 比较两个值是否相等,相等返回true,不相等返回false
    • 如果两个值的类型进行比较,会自动进行类型转换,再比较
    • undefined衍生自null,所以比较时,会返回true
    • NaN不和任何值相等,包括它本身
    • 可以通过isNaN()函数来判断一个值是否是NaN
  • != 不相等
    • 比较两个值是否不相等,不相等返回true,相等返回false
  • ===全等
    • 不会进行类型自动转换,如果两个值类型不同,直接返回false
  • !== 不全等
    • 不会进行类型自动转换,如果两个值类型不同,直接返回true

条件运算符

  • 条件表达式?语句1:语句2;
  • 首先对条件表达式进行求值,如果为true,执行语句1;如果为false,执行语句2
  • 当条件表达式是一个非布尔值时,会现将其转换为布尔值再执行

运算符的优先级

  • 优先级由高到低:
    2. JavaScript基础&实战&高级_第2张图片

3. 流程控制语句

3.1 if语句

if(age>90){
	alert("活着没意思……");
}
else if(age>60){
	alert("你已经退休了")}
else{
	alert("还得奋斗啊")}

3.2 switch…case…语句

  • 在执行时会依次将case后的表达式的值和switch后的条件表达式的值进行全等比较
    • true:从当前case处开始执行代码,通过break确保只执行当前case
    • false:继续向下比较
    • default:所有的比较结果都为false
switch(num){
	case 1:
		console.log("一");
		break;
	case 2:
		console.log("二");
		break;
	case 3:
		console.log("三");
		break; 
	default:
		console.log("非法数字~~");
		break;
}

3.3 while语句

//先判断再执行
while(money<5000){
	money*=1.05;
	count++;
}
//先执行再判断
do{
	money*=1.05;
	count++;
}while(money<5000)

3.4 for循环

for(var i=0;i<10;i++){
	alert(i);
}
  • for循环中的三个部分都可以省略,也可以写在外部
var i=0;
for(;i<10;){
	alert(i++);
}
  • 只写两个分号,是死循环
for(;;){
	alert("hello");
}

3.5 break和continue

break

  • 终止当前循环
  • 可以为循环语句创建一个label,来标识当前的循环
  • label:循环语句
  • 使用break后面跟着一个label,这样break将会结束指定的循环,而不是最近的
  • break label;

continue

  • 跳过当前循环
  • 可以为循环语句创建一个label,来标识当前的循环
  • label:循环语句
  • 使用continue后面跟着一个label,这样continue将会跳过指定的循环的,而不是最近的
  • continue label;

测试程序性能

console.time("test"); //开启计时器,test是计时器的名字
{
	要测试的代码
}
console.timeEnd("test"); //停止计时器
  • 加入break和continue的代码的时间性能会提高

4. 对象

4.1 对象的分类

内建对象

  • 由ES标准中定义的对象,在任何的ES的实现中都可以使用
  • ex:Math String Number Boolean Function Object

宿主对象

  • 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
  • ex:BOM DOM

自定义对象

  • 由开发人员自己创建的对象

4.2 操作对象

//创建对象
var obj=new Object();
//添加属性
obj.name="哪咤";
obj.gender="男";
obj.age=18;
//查看属性
console.log(obj.name);
//修改属性
obj.name="lily";
//删除属性
delete obj.name;

4.3 对象属性名的其他表示方式

obj["123"]=789;
console.log(obj["123"]);
var s="娃哈哈";
obj[s]=789;
console.log(obj[s]);
  • 属性值可以是任意数据类型,甚至可以也是一个对象
var obj=new Object();
var obj2=new Object();
obj2.name="八戒";
obj.test=obj2;
console.log(obj.test.name);
  • in运算符可以检查一个对象中是否含有指定的属性,有则返回true,无则返回false
console.log("test2" in obj);

4.4 基本数据类型和引用数据类型

基本数据类型

  • String Number Boolean Null Undefined

引用数据类型

  • Object

区别

  • JS中的变量都是保存到栈内存中的
  • 基本数据类型的值直接在栈内存中存储,值值之间是独立存在,修改一个变量不会影响其他的变量
  • 对象是保存到堆内存的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当一个通过变量修改属性时,另一个也会受到影响
  • 当比较两个基本数据类型的值时,就是比较值
  • 比较两个引用数据类型时,他比较的是对象的内存地址,如果两个对象是一模一样的,但是地址不同,它也会返回false

4.5 对象字面量

  • 使用对象字面量,可以在创建对象时,直接指定对象的属性
  • 属性名可以加引号也可以不加,建议不加
  • 如果要使用一些特殊的名字,则必须加引号
  • 如果一个属性之后没有其他的属性了,就不要写,
var obj={
	name:"八戒",
	age:28,
	gender:"男",
	test:{name:"沙和尚"}
};

4.6 枚举对象中的属性

  • for…in语句,对象中有几个属性,循环体就会执行几次,每次执行会将对象中的一个属性的名字赋值给变量
//输出对象中的所有属性名
for(var i in obj){
	console.log(i);
}
//输出对象中的所有属性值
for(var i in obj){
	console.log(obj[i]);
}

5.函数

5.1 创建函数

声明法

function fun(){
	console.log("hello");
}

函数表达式法

var fun=function(){
	console.log("hello");
};

立即执行函数

  • 函数定义完,立即被调用,只会执行一次
(function(a,b){
	console.log("a="+a);
	console.log("b="+b);
})(123,456);

5.2 函数特性

  • 万物皆是对象,函数也是
  • 实参可以是一个对象,也可以是一个函数
  • return:返回函数值,可以结束整个函数
var fun=function(mianji()){ //调用函数,相当于使用函数的返回值
	return mianji();
};

var fun2=function(mianji){  //函数对象,相当于直接使用函数对象
	return mianji;
};
  • 对象的属性值可以是任何的数据类型,也可以是个函数
  • 函数也可以成为对象的属性
    • 我们称这个函数是这个对象的方法,调用函数就是调用对象的方法
      Math.sqrt(a):对a进行开方,调用Math的sqrt()方法

5.3 作用域

  • 作用域指一个变量的作用范围

全局作用域

  • 直接编写在script标签中的JS代码,都在全局作用域
  • 全局作用域在页面打开时创建,在页面关闭时销毁
  • 在全局作用域中有一个全局对象window,他代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用
  • 创建的变量都会作为window对象的属性保存,创建的函数都会作为window对象的方法保存
  • 变量的声明提前:
    • 使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值)
  • 函数声明提前:
    • 使用函数声明形式创建的函数function 函数名(){},它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数
    • 使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用

函数作用域

  • 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
  • 每调用一次函数就会创建一个新的函数作用域,它们之间是互相独立的
  • 在函数作用域中可以访问到全局作用域变量,在全局作用域中无法访问到函数作用域的变量
  • 当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用,如果没有则向上一级作用域中寻找,直到找到全局作用域
  • 在函数作用域内访问全局变量可以使用window
  • 在函数中,不使用var声明的变量都会成为全局变量
  • 定义形参就相当于在函数作用域中声明了变量

5.4 debug

  • F12->source->敲断点->刷新->右键变量->add to watches

5.5 this

  • 解析器在调用函数时每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象
  • 这个对象我们称为函数执行的上下文对象
  • 根据函数的调用方式的不同,this会指向不同的对象
    • 以函数的形式调用时,this永远都是window
    • 以方法的形式调用时,this就是调用方法的那个对象
var name="全局"function fun(){
	console.log(this.name);
}
var obj={
	name:"孙悟空",
	sayName:fun
}
var obj2={
	name:"沙和尚",
	sayName:fun
}
fun(); //全局
obj.sayName();  //孙悟空
obj2.sayName();  //沙和尚

5.6 使用工厂方法创建对象

  • 使用该方法可以大批量地创建对象
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;
}
var obj2=createPerson("乐乐",25,"女");
var obj3=createPerson("天天",26,"男");
var obj4=createPerson("文文",27,"女");
obj2.sayName();//乐乐
obj3.sayName();//天天
obj4.sayName();//文文

问题:

  • 使用工厂方法创建的对象,使用的构造函数都是Object
  • 创建的对象都是Object这个类型,就导致我们无法区分出多种不同类型的对象

5.7 构造函数

解决方法:

  • 创建一个构造函数,专门用来创建Person对象的
  • 构造函数就是一个普通的函数,创建方式和普通函数没有区别
  • 不同的是构造函数习惯上首字母大写
  • 构造函数和普通函数调用方式不同
    • 普通函数直接调用
    • 构造函数需要使用new关键字

构造函数的执行流程

  • 立即创建一个新的对象
  • 将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象
  • 逐行执行函数中的代码
  • 将新建的对象作为返回值返回

  • 使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类
  • 实例:同一个构造函数创建的对象称为该构造函数的实例,也叫该类的实例
  • 使用instanceof可以检查一个对象是否是一个类的实例
    console.log(per instanceof Person);
  • 所有的对象都是Object的实例
function fun(){
		alert(this.name);
	}
function Person(name,age,gender){
	this.name=name;
	this.age=age;
	this.gender=gender;
	this.sayName=fun; 
}
function Dog(){
}
var per=Person();
var per2=new Person("乐乐",25,"女");
var per3=new Person("tt",26,"男");
var per4=new Person("ww",27,"女");
var dog=new Dog();
console.log(per);
console.log(dog);

问题:

  • 将函数定义在全局作用域,污染了全局作用域的命名空间
  • 定义在全局作用域中也很不安全

5.8 原型prototype

  • 我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
  • 这个属性对应着一个对象,这个对象就是我们所谓的原型对象
  • 如果函数作为普通函数调用prototype时没有任何作用
  • 当函数以构造函数的形式调用时,它所创建的实例对象中都会有一个隐含属性
    • 指向该构造函数的原型对象,我们可以通过__proto__来访问该属性
  • 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问这个原型对象
  • 当我们访问一个对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用
  • 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了
    2. JavaScript基础&实战&高级_第3张图片
function Person(name,age,gender){
	this.name=name;
	this.age=age;
	this.gender=gender;
}
Person.prototype.sayName=function(){
	alert("this.name");
}
function Dog(){
}
var per=Person();
var per2=new Person("乐乐",25,"女");
var per3=new Person("tt",26,"男");
var per4=new Person("ww",27,"女");
var dog=new Dog();
console.log(per);
console.log(dog);
  • 使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
console.log("name" in mc) //true
  • 可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性
console.log(mc.hasOwnProperty("name"));//false
console.log(mc.__proto__.hasOwnProperty("name"));//true
  • 原型对象也是对象,所以它也有原型
  • 当我们使用一个对象或方法时
    • 先在自身中寻找,有则直接使用
    • 没有则去原型对象中寻找,原型对象中有则使用
    • 没有则去原型的原型中寻找,直到找到Object对象的原型
    • Object对象的原型没有原型,如果Object中依然没有找到,则返回undefined
console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));//false
console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));//true

tostring

  • 当我们直接在页面中打印一个对象时,事实上是输出的toString()方法的返回值
  • toString()方法在对象的原型函数的原型函数里
  • 如果我们希望在输出对象时不输出[object object],可以自定义构造函数的原型函数里toString()
Person.prototype.toString=function(){
	return "Person[name="+this.name+",age="+this.age+",gender="this.gender+"]";
};

5.9 垃圾回收(GC)

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

5.10 函数的方法

call()和apply()

  • 可以让一个函数成为指定任意对象的方法进行调用
  • 函数调用两个方法时都会调用函数执行
  • 调用两者时,可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this
  • call()方法可以将实参在对象之后依次传递
  • apply()方法需要将实参封装到一个数组中统一传递
function fun(a,b){
	console.log(a);
	console.log(b);
	alert(this.name)
}
var obj={
	name:"obj"
}
var obj2={
	name:"obj2"
}
fun.call(obj,2,3);//2,3,obj
fun.apply(obj2,[2,3]);//2,3,obj2

5.11 arguments

  • 在调用函数时,浏览器每次都会传递进两个隐含的参数:
  • 函数的上下文对象this
  • 封装实参的对象arguments
    • arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度
    • 在调用函数时,我们传递的实参都会在arguments中保存
    • arguments.length可以用来获取实参的长度
    • 我们即使不定义形参,也可以通过arguments来使用实参,只不过比较麻烦
      • arguments[0]表示第一个实参
      • arguments[1]表示第二个实参
    • 它里面有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象
function fun(){
	console.log(arguments[1]);//2
	console.log(arguments.length);//2
	console.log(arguments.callee==fun);//true
}
fun(1,2);

5.12 包装类

  • JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
  • String():可以将基本数据类型字符串转换为String对象
  • Number():可以将基本数据类型数字转换为Numbe对象
  • Boolean():可以将基本数据类型布尔值转换为Boolean对象
  • 注意:我们在实际应用中不会使用基本数据类型的对象,因为对象是引用数据类型,在做一些比较时会出现错误
  • 方法和属性只能添加给对象,不能添加给基本数据类型
  • 当我们对一些基本数据类型的值去调用属性和方法时(类型转换),浏览器会临时使用包装类将其转换为对象,然后再调用对象的属性和方法,调用完以后,立即将其转换为基本数据类型。

6. 内建对象

6.1 数组

对象法创建数组

var arr=new Array(10,20,30);//创建数组对象"10,20,30"
var arr=new Array(3);//创建一个长度为3的数组对象",,"
console.log(typeof arr);//object
arr[0]=10;//向数组中添加元素
console.log(arr[3]);//读取数组中的元素
console.log(arr.length);//获取数组对象的长度

字面量法创建数组

var arr=[1,2,3,4,6]; //创建数组对象"1,2,3,4,6"
var arr=[2];//创建数组对象"2"
arr=["hello",1,true,null,undefined];//数组中的元素可以是任意的数据类型
arr=[{name:"ljw"},{name:"mz"}];//也可以是对象
arr=[function(){alert(0)},function(){alert(1)}];//也可以是函数
arr[0]();//读取数组里的函数
arr=[[1,2,3],[3,4,5],[5,6,7]];//二维数组

数组的方法

push()

  • 向数组末尾添加一个或多个元素,并返回数组的新的长度
var arr=["wea"];
result=arr.push("zs","lisi");
console.log(result);//3

pop()

  • 删除数组的最后一个元素,并将被删除的元素返回
result=arr.pop();
console.log(result);//lisi

unshift()

  • 向数组开头添加一个或多个元素,并返回新的数组长度
result=arr.unshift("rose");
console.log(result);//3

shift()

  • 删除数组第一个元素,并将被删除的元素返回
result=arr.shift();
console.log(result);//"rose"

slice()

  • 从数组中截取指定范围的元素
  • 不会改变原始数组,而是将截取到的元素封装到一个新数组中返回
  • 参数:[srart,end)
  • 第二个参数不写,会截取从开始索引往后的所有元素
  • 索引为负值,则从后往前计算,-1倒数第一个,-2倒数第二个
var arr=[0,1,2,3,4];
var result=arr.slice(1,2);
console.log(result);//1

splice()

  • 删除指定范围内的元素
  • 会影响到原数组,会将指定元素从原数组中删除,并将删除的元素作为返回值返回
  • 参数:
    • 第一个:开始位置的索引
    • 第二个:删除的数量
    • 第三个及以后:可以在开始位置索引处插入新的一些元素
var arr=[0,1,2,3,4];
var result=arr.splice(1,2,3,4);
console.log(arr);//[0,3,4,3,4]
console.log(result);//[1,2]

concat()

  • 连接两个或多个数组,并将新的数组返回,该方法不会对原数组产生影响
var arr=[1,2,3];
var arr2=[4,5,6];
var arr3=[7,8,9];
var result=arr.concat(arr2,arr3,"ljw","hhh");
console.log(result);//1,2,3,4,5,6,7,8,9,ljw,hhh

join()

  • 该方法可以将数组转换为一个字符串
  • 该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回
  • 在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符
  • 默认是,,若想没有连接符join("")
arr=["ljw","nhy","hhh"];
result=arr.join("@");
console.log(typeof result);//string 
console.log(result);//ljw@nhy@hhh

reverse()

  • 反转数组,会直接修改原数组
var arr=[1,2,3,4];
arr.reverse();
console.log(arr);//4,3,2,1

sort()

  • 可以用来对数组元素进行排序,会影响原数组
  • 默认按照Unicode编码进行排序
  • 即使对于纯数字排序,也会按照Unicode编码来排序,可能会得到错误结果
  • 可以自己指定排序规则
    • 在sort()中添加一个回调函数来指定排序规则
    • 浏览器根据回调函数返回值决定元素的顺序
      • 返回大于0的值,元素交换位置
      • 返回小于等于0的值,元素位置不变
var arr=["e","b","d","a","c"];
arr.sort();
console.log(arr);//"a,b,c,d,e"

var arr2=[11,23,4,8,10,55];
arr2.sort();
console.log(arr2);//10,11,23,4,55,8

arr.sort(function(a,b){
	return a-b;//升序排列
	return b-a;//降序排列
})
console.log(arr2);//4,8,10,11,23,55

遍历数组

for循环

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

forEach()

  • 该方法只支持IE8以上的浏览器
  • forEach()方法需要一个函数作为参数
    • 像这种函数,由我们创建但是不由我们调用,我们称为回调函数
    • 数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素以实参的形式传递进来,我们可以来定义形参,来读取这些内容
  • 浏览器会在回调函数中传递三个参数:
    • 第一个参数:当前正在遍历的元素;
    • 第二个参数:当前正在遍历的元素的索引
    • 第三个参数:正在遍历的数组
arr.forEach(function(value.index,obj){
	console.log(value);
	console.log(index);
	console.log(obj);
});

6.2 Date

  • 如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间
  • 创建一个指定的时间对象
    • 月/日/年 时:分:秒
var d =new Date();
console.log(d);
var d2 =new Date("12/02/2018 11:00:30");

getDate()

  • 获取当前日期对象是几号
var date =d2.getDate();
console.log(date);//2

getDay()

  • 获取当前日期对象是周几
  • 返回0-6
  • 0:周日,1:周一
var day =d2.getDay();
console.log(day);//0

getMonth()

  • 获取当前日期对象是几月
  • 返回0-11
  • 0:一月,1:二月
var month =d2.getMonth();
console.log(month);//11

getFullYear()

  • 获取当前日期对象的年份
var year =d2.getFullYear();
console.log(year);//2018

getTime()

  • 获取当前日期对象的时间戳
  • 时间戳,从格林威治标准时间的1970年1月1日,0时0分0秒到当前日期所花费的毫秒数(1秒=1000毫秒)
  • 计算机底层在保存时间时使用的都是时间戳,为了统一单位
var time =d2.getTime();
console.log(time);//1432398752823
//获取执行当前代码的时间的时间戳
time=Date.now();
console.log(time);
  • 利用时间戳来测试代码的执行的性能
var start=Date.now();
for(var i=0;i<100;i++){
	console.log(i);
}
var end=Date.now();
console.log(end-start);

6.3 Math

  • Math和其他对象不同,它不是一个构造函数,它属于一个工具类,里面封装了数学运算相关的属性和方法
Math.PI//表示圆周率
Math.abs(-2)//-2的绝对值为2
Math.ceil(1.4)//向上取整为2
Math.floor(1.4)//向下取整为1
Math.round(1.4)//四舍五入为1
Math.random()//生成0-1(不包括0和1)之间的随机数
Math.round(Math.random()*(y-x)+x)//生成x-y之间的随机数
Math.max(10,45,30,100)//求最大值为100
Math.min(10,45,30,100)//求最小值为10
Math.pow(x,y)//返回x的y次幂
Math.sqrt(4)//对4开方位2

6.4 String

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

属性

length

  • 可以用来获取字符串的长度
console.log(str.length);

方法

charAt()

  • 返回字符串中指定位置的字符
var str="ljw";
var res=str.charAt(1);
console.log(res);//j

charCodeAt()

  • 获取指定位置字符的字符编码(Unicode编码)
var str="Hello";
var res=str.charCodeAt(0);
console.log(res);//72

fromCharCode()

  • 根据字符编码去获取字符
var res=str.fromCharCode(20045);
console.log(res);//"乍"
  • 如果编码是16进制,(0x2692)

concat()

  • 用来连接两个或多个字符串
  • 作用和+一样
var res=str.concat("你好","再见");
console.log(res);//“你好再见”

indexOf()

  • 该方法可以检索一个字符串中是否含有指定内容
  • 如果字符串中含有该内容,则会返回其第一次出现的索引;如果没有找到,则返回-1
  • 可以指定一个第二个参数,指定开始查找的位置
var str="hello ljw";
var res=str.indexOf("l",3);
console.log(res);//3

lastIndexOf()

  • 该方法的用法和indexOf()一样,不同的是从后往前找
var str="hello ljw";
var res=str.lastIndexOf("l",3);
console.log(res);//2

slice()

  • 可以从字符串中截取指定的内容
  • 不会影响原字符串,而是将截取到内容返回
  • 参数:[start,end)
var str="hello ljw";
var res=str.slice(1,2);
var res2=str.slice(3);
var res3=str.slice(1,-1);
console.log(res);//e
console.log(res2);//lo ljw
console.log(res3);//ello lj

substring()

  • 可以从字符串中截取指定的内容,与slice()类似
  • 参数:[start,end)
  • 不同的是这个方法不能接受负值作为参数,如果传递了一个负值,则默认为0
  • 还可以自动调整参数位置,如果第二个参数小于第一个,则自动交换
var str="hello ljw";
var res=str.substring(1,2);
var res2=str.substring(3);
var res3=str.substring(1,-1);
console.log(res);//e
console.log(res2);//lo ljw
console.log(res3);//h

split()

  • 可以将一个字符串拆分为一个数组
  • 如果传递一个空串作为参数,则会将每个字符都拆分为数组中的一个元素
var str="hello ljw";
var res=str.split("o");
console.log(res[0]);//hell
console.log(res[1]);// ljw

toUpperCase()

  • 可以将一个字符串转换为大写并返回
var str="hello ljw";
var res=str.toUpperCase();
console.log(res);//HELLO LJW

toLowerCase()

  • 可以将一个字符串转换为小写并返回
var str="HELLO LJW";
var res=str.toLowerCase();
console.log(res);//hello ljw

7. 正则表达式

7.1 创建正则表达式的对象

  • var 变量=new RegExp("正则表达式","匹配模式");
  • 匹配模式:
    • i:忽略大小写
    • g:全局匹配模式
var reg=new RegExp("a");
var str="abc";
reg.test(str);//str中含有a,返回true

var reg2=new RegExp("a","i");
var str2="Abc";
reg2.test(str2);//true

7.2 使用字面量来创建正则表达式

  • var 变量=/正则表达式/匹配模式
  • 使用字面量的方式创建更加简单
  • 使用构造函数创建更加灵活
var reg=/a/i;
var str="abc";
reg.test(str);//str中含有a,返回true

var reg2=/a|b/;//检测字符串中是否有a或b
reg2.test(str);//true

var reg3=/[a-z]/;//检测字符串中是否有任意小写字母
reg3.test(str);//true
var reg3=/[A-Z]/;//检测字符串中是否有任意大写字母
reg3.test(str);//false
var reg3=/[0-9]/;//检测字符串中是否有任意数字
reg3.test(str);//false

var reg4=/[^ab]/;//检测字符串中是否有除了ab以外的元素
reg4.test(str);//true

var reg5=/a{3}/;//检测字符串中是否有连续出现3次的a,即"aaa"
reg5.test(str);//false
var reg5=/(ab){3}/;//检测字符串中是否有连续出现3次的ab,即"ababab"
reg5.test(str);//false
var reg5=/(ab){1,3}/;//检测字符串中是否有连续出现1-3次的ab,即"ab"或者“abab"或者"ababab"
reg5.test(str);//true
var reg5=/(ab){1,}/;//检测字符串中是否有连续出现1次即以上的ab,即"ab"或者“abab"或者"ababab"……
reg5.test(str);//true
var reg5=/(ab)+/;//检测字符串中是否有连续出现1次即以上的ab,即"ab"或者“abab"或者"ababab"……
reg5.test(str);//true
var reg5=/(ab)*/;//检测字符串中是否有连续出现0次即以上的ab,即""或者"ab"或者“abab"或者"ababab"……
reg5.test(str);//true
var reg5=/(ab)?/;//检测字符串中是否有连续出现0次或1次的ab,即""或者"ab"
reg5.test(str);//true

var reg6=/^a/;//检测字符串中是否以a开头
reg6.test(str);//true
var reg6=/a$/;//检测字符串中是否以a结尾
reg6.test(str);//false
var reg6=/^a$/;//只有当str="a"才为true
reg6.test(str);//false

var reg7=/\./;//.表示任意字符,使用\作为转义字符,\.检查字符串中是否有.
reg7.test(str);//false
var reg7=/\\/;//.表示任意字符,使用\作为转义字符,\\检查字符串中是否有\
reg7.test(str);//false
var reg7=new RegExp("\\.");//构造函数的参数是字符串,\是转义字符,需要用\\代替,检查字符串中是否有.
reg7.test(str);//false
var reg7=new RegExp("\\\\");//构造函数的参数是字符串,\是转义字符,需要用\\代替,检查字符串中是否有\
reg7.test(str);//false

reg=/\w/;//任意字母、数字、_ [A-z0-9_]
reg=/\W/;//除了字母、数字、_ [^A-z0-9_]
reg=/\d/;//任意数字[0-9]
reg=/\D/;//除了数字[^0-9]

reg=/\s/;//空格
reg=/\S/;//除了空格
str=str.replace(/^\s*|\s*$/g,"")去除字符串开头和结尾的空格

reg=/\b/;//单词边界
reg=/\B/;//除了单词边界
reg=/\bchild\b/;
reg.test("hello achildren");//false
reg.test("hello child");//true


  • 手机号规则
vae phoneStr="10854265152";
var phoneReg=/^1[3-9][0-9]{9}$/;
console.log(phoneReg.test(phoneStr));//false
  • 电子邮件
 var emailReg=/^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;

7.3 字符串和正则相关的方法

split()

  • 方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串
  • 这个方法即使不指定全局匹配,也会全都拆分
var str="1a2b3c4d5e";
var res=str.split(/[A-z]/);
console.log(res);//"1,2,3,4,5"

search()

  • 可以搜索字符串中是否含有指定内容
  • 如果搜到指定内容,则会返回第一次出现的索引,如果没有返回-1
  • 可以接受一个正则表达式作为参数
  • 即使设置全局匹配,也只会查找第一个
var str="hello abc hello ";
var res=str.search(/a[bef]c/);
console.log(res);//true

match()

  • 可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
  • 默认情况下只会找到第一个符合条件的内容,可以设置全局匹配模式
  • 可以设置多个匹配模式,且顺序无所谓
  • match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果
var str="1a2b3c4d5eCDE";
var res=str.search(/[a-z]/gi);
console.log(res);//"a,b,c,d,e,C,D,E"

replace()

  • 可以将字符串中指定的内容替换为新的内容
  • 参数:
    • 被替换的内容,可以接受一个正则表达式作为参数
    • 新的内容
  • 默认只会替换第一个
var str="1a2Ab3c4ad5eCDE";
var res=str.replace(/a/gi,"$");
console.log(res);//"1$2$b3c4$d5eCDE"

二、DOM

1. DOM简介

1.1 DOM

2. JavaScript基础&实战&高级_第4张图片

1.2 节点Node

  • 构成HTML文档最基本单元
  • 常用节点分为四类
    • 文档节点:整个HTML文档
    • 元素节点:HTML文档中的HTML标签
    • 属性节点:元素的属性
    • 文本节点:HTML标签中的文本内容
  • 浏览器已经为我们提供文档节点对象,这个对象是window属性,可以在页面中直接使用,文档节点代表的是整个网页
console,log(document);//[object HTMLDocument]
//获取按钮对象
var btn=document.getElementById("btn");
btn.innerHTML="按我呀";

1.3 事件

  • 用户和浏览器之间的交互行为

直接在标签里绑定事件

<button id="btn" onclick="alert(‘讨厌’)">我是一个按钮</button>

为对象绑定事件

  • onload事件会在整个页面加载完成后才触发
  • 为window绑定一个onload事件:
    • 可以确保我们的代码执行时所有的DOM对象已经加载完毕了
    • 这样就可以把JS写在head里
window.onload=function(){
	//获取按钮对象
	var btn=document.getElementById("btn");

	//为按钮的对应事件绑定处理函数的形式来相应事件
	btn.onclick=function(){
		alert("你还点~~")
	}
}

2. DOM查询

2.1 获取元素节点

通过document对象调用

  • document.getElementById()
  • document.getElementsByTagName()[i]:返回一个类数组的第i个元素
  • document.getElementsByName()
  • document.getElementsByClassName()不支持IE8及以下的浏览器
var body=document.body;//获取body元素
var html=document.documentElement;//获取html根标签
var all=document.all;//获取页面的所有元素
var all=document.getElementByTagName("*");

获取元素内部HTML代码

  • 对于自结束标签,这个属性没有意义
  • console.log(btn.innerHTML):获取的内容有HTML标签
  • innerText:没有HTML标签

读取元素节点属性

  • 元素.id
  • 元素.name
  • 元素.value
  • 元素.className

2.2 获取元素节点的子节点

通过具体的元素节点调用

  • 元素.getElementByTagName():返回当前节点的指定标签名后代节点
  • 元素.childNodes:获取包括文本在内的所有子节点,标签间的空白也会当成文本节点(IE8以下不会)
  • 元素.children:获取包括文本在内的所有子元素
  • 元素.firstChild:获取包括文本在内的第一个子节点,标签间的空白也会当成文本节点
  • 元素.lastChild:获取包括文本在内的最后一个子节点,标签间的空白也会当成文本节点

2.3 获取父节点和兄弟节点

通过具体的元素节点调用

  • 元素.parentNode:获取包括文本在内的父节点,标签间的空白也会当成文本节点(IE8以下不会)
  • 元素.previousSibling:获取包括文本在内的前一个兄弟节点
  • 元素.previousElementSibling:获取前一个兄弟元素
  • 元素.nextSibling:获取包括文本在内的下一个兄弟节点

2.3 选择器

document.querySelector()

  • 根据一个CSS选择器来查询一个元素节点对象
  • 如果满足条件的元素有多个,只会返回第一个
var div=document.querySelector(".box1 div");

document.querySelectorAll()

  • 返回一个数组,即使满足条件的元素只有一个
var div=document.querySelectorAll(".box1 div");

3. DOM增删改

3.1 为一个节点添加一个子节点

父节点.appendChild(子节点);

var li=document.createElement("li");//创建元素节点对象
var gzText=document.createTextNode("广州");//创建文本对象
li.appendChild(gzText);//向一个父节点中添加一个新的子节点
var city=document.getElementById("city")//获取id为city的节点
city.appendChild(li)//将广州添加到city下

父节点.innerHTML+="子节点"

  • 这种方式父节点下的所有节点都会更新
city.innerHTML+="
  • 广州
  • "
    ;
    • 推荐使用两者结合的方式
    var li=document.createElement("li");
    li.innerHTML="广州";
    city.appendChild(li);
    

    3.2 在一个节点前面插入一个节点

    父节点.insertBefore(新节点,旧节点);

    var li=document.createElement("li");//创建元素节点对象
    var gzText=document.createTextNode("广州");//创建文本对象
    li.appendChild(gzText);//向一个父节点中添加一个新的子节点
    var bj=document.getElementById("bj")//获取id为bj的节点
    var city=document.getElementById("city")//获取id为city的节点,city是北京和广州的父节点
    city.insertBefore(li,bj)//li为新节点,bj为旧节点
    

    3.3 替换节点

    父节点.replaceChild(新节点,旧节点);

    var li=document.createElement("li");//创建元素节点对象
    var gzText=document.createTextNode("广州");//创建文本对象
    li.appendChild(gzText);//向一个父节点中添加一个新的子节点
    var bj=document.getElementById("bj")//获取id为bj的节点
    var city=document.getElementById("city")//获取id为city的节点,city是北京和广州的父节点
    city.replaceChild(li,bj)//li为新节点,bj为旧节点
    

    3.4 删除节点

    父节点.removeChild(子节点);

    var bj=document.getElementById("bj")//获取id为bj的节点
    var city=document.getElementById("city")//获取id为city的节点,city是北京的父节点
    city.removeChild(bj)//删除北京节点
    

    子节点.parentNode.removeChild(子节点);

    var bj=document.getElementById("bj")//获取id为bj的节点
    bj.parentNode.removeChild(bj)//删除北京节点
    

    4. DOM修改样式

    4.1 改元素内联样式

    元素.style.样式名=样式值

    • 注意:CSS中样式名含-的在JS中不合法,要改成驼峰命名法
      background-color改成backgroundColor
    • 通过style属性设置的样式都是内联样式,而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示
    • 但是如果在样式中写了!important,则此时样式会有最高的优先级,即使通过JS也不能覆盖该样式,此时会导致JS修改样式失效,所以尽量不要为样式添加!important
    var box1=document.getElementById("box1");
    var btn01=document.getElementById("btn01");
    btn01.onclick=function(){
    	box1.style.width="300px";
    	box1.style.backgroundColor="yellow";
    }
    

    4.2 获取元素样式

    获取元素的内联样式(可改)

    var box1=document.getElementById("box1");
    var btn01=document.getElementById("btn01");
    btn01.onclick=function(){
    	alert(box1.style.width);
    }
    

    获取元素正在显示的样式(只读)

    元素.currentStyle.样式名

    • 只有IE浏览器支持
    var box1=document.getElementById("box1");
    var btn01=document.getElementById("btn01");
    btn01.onclick=function(){
    	alert(box1.currentStyle.width);
    }
    

    getComputedStyle(元素名,null).样式名

    • 不支持IE8及以下浏览器
    • 两个参数
      • 第一个:要获取样式的元素
      • 第二个:可以传递一个伪元素,一般都传null
    • 如果获取的样式没有设置,则会获取到真实的值,而不是默认值
    • 比如:没有设置width,它不会获取到auto,而是一个长度
    alert(getComputedStyle(box1,null).width);
    
    • 自定义一个都兼容的浏览器的函数
    • 对象找不到会返回错误
    • 属性找不到会返回undefined
    function getStyle(obj,name){
    	if(window.getComputedStyle){
    		return getComputedStyle(obj,null)[name];
    	}else{
    		return obj.currentStyle[name];
    	}
    }
    

    4.3 其他样式相关属性

    clientWidth clientHeight

    • 获取元素的可见宽度和高度
    • 这些属性都不带px,返回的是数字,可以直接进行计算
    • 会获取元素的宽度和高度,包括内容区和内边距
    • 只读,不能修改
    alert(box1.clientWidth);
    alert(box1.clientHeight);
    

    offsetWidth offsetHeight

    • 获取元素的整个的宽度和高度,包括内容区、内边距和边框
    alert(box1.offsetWidth);
    alert(box1.offsetHeigth);
    

    offsetParent

    • 用来获取当前元素的定位父元素
    • 会获取到离当前元素最近的开启了定位的祖先元素(position不是默认值)
    • 如果所有的祖先元素都没有开启定位,则返回body
    var op=box1.offsetParent;
    alert(op.id);
    

    offsetLeft offsetTop

    • 当前元素相对于其定位父元素的水平偏移量和垂直偏移量
    alert(box1.offsetLeft);
    

    scrollWidth scrollHeight

    • 可以获取元素整个滚动区域的宽度和高度
    alert(box4.clientHeight);//300
    alert(box4.scrollHeight);//450
    

    scrollLeft scrollTop

    • 可以获取水平滚动条滚动的距离
    • 可以获取垂直滚动条滚动的距离
    alert(box4.scrollLeft);
    alert(box4.scrollRight);
    
    • scrollHeight-scrollTop==clientHeight时,说明垂直滚动条滚动到底了
    • scrollWidth-scrollLeft==clientWidth时,说明水平滚动条滚动到底了

    5. 事件

    5.1 事件对象

    • 当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数
    • 在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标、键盘哪个按键被按下,鼠标滚轮滚动方向……

    onscroll事件

    • 该事件会在元素的滚动条滚动时触发
    var info=document.getElementById("info");
    var inputs=document.getElementsByTagName("input");
    info.onscroll=function(){
    	if(info.scrollHeight-info.scrollTop==info.clientHeight){
    		inputs[0].disabled=false;
    		inputs[1].disabled=false;
    	}
    }
    

    onmousemove事件

    • 该事件将会在鼠标在元素中移动时被触发

    clientX clientY 事件对象的属性

    • 获取鼠标指针在当前的可见窗口的坐标
    • div的偏移量,是相对于整个页面的

    pageX pageY

    • 获取鼠标相对于当前页面的坐标
    • 在IE8中不支持
    areaDiv.onmousemove=function(event){
    	//处理浏览器兼容问题
    	event=event||window.event;
    	
    	var x=event.clientX;
    	var y=event.clientY;
    	showMsg.innerHTML="x="+x+",y="+y;
    }
    

    div跟随鼠标移动

    • 获取浏览器滚动条对象,chrome认为浏览器的滚动条是body的,火狐认为是html的
    //处理浏览器兼容问题
    var st=document.body.scrollTop||document.documentElement.scrollTop;
    var sl=document.body.scrollLeft||document.documentElement.scrollLeft;
    //获取鼠标指针在当前的可见窗口的坐标
    var left=event.clientX;
    var top=event.clientY;获取鼠标指针在当前的可见窗口的坐标
    //div的偏移量,是相对于整个页面的,需要加上滚动条滚动的距离
    box1.style.left=left+sl+"px";
    box1.style.top=top+st+"px";
    

    5.2 事件的冒泡

    • 事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发
    • 在开发中大部分的冒泡都是有用的
    • 如果不希望冒泡可以取消
    box1.onclick=function(event){
    	event=event||window.event;
    	event.cancelBubble=true;
    }
    

    事件的委派

    • 将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事情触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。
    • 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
    • 触发事件的对象event.target
    ul.onclick=function(event){
    	event=event||window.event;
    	//如果触发事件的对象是我们期望的元素则执行否则不执行
    	if(event.target.className=="link"){
    		alert("我是ul的单击响应函数");
    	}
    }
    

    5.3 事件的绑定

    addEventListener()

    • 可以同时为一个元素的相同事件同时绑定多个响应函数
    • 当事件被触发时,响应函数将会按照函数的绑定顺序执行
    • 参数:
      • 事件的字符串,不要on
      • 回调函数,当事件触发时该函数会被调用
      • 是否在捕获阶段触发事件,需要一个布尔值,一般都传false
    • 这个方法不支持IE8及以下的浏览器
    btn01.addEventListener("click",function(){
    	alert(1);
    },false);//1
    btn01.addEventListener("click",function(){
    	alert(2);
    },false);//2
    btn01.addEventListener("click",function(){
    	alert(3);
    },false);//3
    

    attachEvent()

    • 在IE8中使用来绑定事件
    • 参数:
      • 事件的字符串,要on
      • 回调函数,当事件触发时该函数会被调用
    • 可以同时为一个元素的相同事件同时绑定多个响应函数,但是顺序相反
    btn01.attachEvent("onclick",function(){
    	alert(1);
    });//3
    btn01.attachEvent("onclick",function(){
    	alert(2);
    });//2
    btn01.attachEvent("onclick",function(){
    	alert(3);
    });//1
    

    解决兼容

    function bind(obj,eventStr,callback){
    	if(obj.addEventListener){
    		obj.addEventListener(eventStr,callback,false);
    	}else{
    		obj.attachEvent("on"+eventStr,function(){
    			callback.call(obj);//解决callback里的this不是obj而是window的问题
    		});
    	}
    }
    

    拖拽box1元素

    • 当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
    • 当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
    • 当鼠标松开时,被拖拽元素固定在当前位置 onmouseup
    var box1=document.getElementById("box1");
    box1.onmousedown=function(){
    	//div的偏移量 鼠标.clientX-元素.offsetLeft
    	//div的偏移量 鼠标.clientY-元素.offsetTop
    	var ol=event.clientX-box1.offsetLeft;
    	var ot=event.clientY-box1.offsetTop;
    	
    	document.onmousemove=function(event){
    		event=event||window.event;
    		var left=event.clientX-ol;//使鼠标位置不要固定在左上角而是可以固定在box1的任意位置
    		var top=event.clientY-ot;
    		box1.style.left=left+"px";
    		box1.style.top=top+"px";
    	};
    	document.onmouseup=function(){
    		document.onmousemove=null;
    		document.onmouseup=null;
    	}
    }
    
    • 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖拽功能的异常
    • 如果不希望发生这个行为,可以通过return false 来取消默认行为
    • 但对IE8无效
    function drag(obj){
    	var obj=document.getElementById("obj");
    	obj.onmousedown=function(event){
    		//设置box1捕获所有鼠标按下的事件
    		obj.setCapture && obj.setCapture();//处理兼容问题
    	
    		event=event||window.event;
    		//div的偏移量 鼠标.clientX-元素.offsetLeft
    		//div的偏移量 鼠标.clientY-元素.offsetTop
    		var ol=event.clientX-obj.offsetLeft;
    		var ot=event.clientY-obj.offsetTop;
    	
    		document.onmousemove=function(event){
    			event=event||window.event;
    			var left=event.clientX-ol;//使鼠标位置不要固定在左上角而是可以固定在box1的任意位置
    			var top=event.clientY-ot;
    			obj.style.left=left+"px";
    			obj.style.top=top+"px";
    		};
    		document.onmouseup=function(){
    			document.onmousemove=null;
    			document.onmouseup=null;
    			obj.releaseCapture && obj.releaseCapture();
    		};
    		return false;
    	};
    };
    
    

    滚轮的事件

    • 当鼠标滚轮向下滚动时,box1变长;当滚轮向上滚动时,box1变短

    • onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,但是火狐不支持该属性

    • 在火狐中需要使用DOMMouseScroll来绑定滚动事件,注意该事件需要通过addEventListener()函数绑定

    • event.wheelDelta可以获取鼠标滚轮滚动方向,向上滚120,向下滚-120,我们不看值的大小,只看正负,火狐不支持

    • event.detail火狐使用这个来获取滚动的方向,向上滚-3向下滚3

    box1.onmousewheel=function(event){
    	event=event||window.event;
    	if(event.wheelDelta>0||event.detail<0){
    		box1.style.height=box1.clientHeight-10+"px";
    	}else{
    		box1.style.height=box1.clientHeight+10+"px";
    	}
    	//使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
    	//需要使用event来取消默认行为event.preventDefault();
    	//但是IE8不支持,直接调用会报错
    	event.preventDefault&&event.preventDefault();
    	//当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,这是浏览器的默认行为,如果不希望发生,则可以取消默认行为
    	return false;
    };
    bind(box1,"DOMMouseScroll",box1.onmousewheel);
    

    键盘事件

    onkeydown

    • 按键被按下
    • 如果一直按着某个按键不松手,则事件会一直触发
    • 连续触发时,第一次和第二次之间会间隔稍微长一些,其他的会非常快,这种设计是为了防止误操作的发生

    onkeyup

    • 按键被松开
    • 键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document

    event.keyCode

    • 获取按键的编码

    event.altKey event.ctrlKey event.shiftKey

    • 判断alt ctrl shift 是否被按下
    document.onkeydown=function(){
    	if(event.keyCode===89 && event.ctrlKey){
    		console.log("ctrl和y都被按下了");
    	}
    };
    
    • 使文本框中不能输入数字
    input.onkeydown=function(event){
    	event=event||window.event;
    	if(event.keyCode>=48 && event.keyCode<=57){
    		//在文本框中输入内容属于onkeydown的默认行为
    		//如果在onkeydown中取消默认行为,则输入的内容不会出现在文本框中
    		return false;
    	}
    }
    
    • 使div可以根据不同的方向键向不同的方向移动
    • 37,38,39,40左上右下
    document.onkeydown=function(event){
    	event=event||window.event;
    	var speed=10;
    	if(event.ctrlKey){
    		speed=500;
    	}
    	switch(event.keyCode){
    		case 37:
    			box1.style.left=box1.offsetLeft-speed+"px";
    			break;
    		case 38:
    			box1.style.top=box1.offsetTop-speed+"px";
    			break;
    		case 39:
    			box1.style.left=box1.offsetLeft+speed+"px";
    			break;
    		case 40:
    			box1.style.top=box1.offsetTop+speed+"px";
    			break;
    		default:
    			break;
    	}
    }
    

    三、BOM

    1. BOM对象

    • 浏览器对象模型
    • BOM可以使我们通过JS来操作浏览器
    • 在BOM中为我们提供了一组对象用来完成对浏览器的操作

    1.1 Window

    • 代表整个浏览器的窗口,同时window也是网页中的全局对象
    • 这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用

    1.2 Navigator

    • 代表当前浏览器的信息,通过该对象可以来识别不同的浏览器
    • 一般只使用userAgent来判断浏览器的信息,返回一个字符串包含浏览器信息
    • 如果通过UserAgent不能判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息
    var ua=navigator.userAgent;
    if(/firefox/i.test(ua)){
    	alert("你是火狐!")
    }else if(/chrome/i.test(ua)){
    	alert("你是chrome!")
    }else if(/msie/i.test(ua)){ //IE11不能通过这个方法判断
    	alert("你是IE!")
    }else if("ActiveXObject" in window){
    	alert("你是IE11,枪毙了你~")
    }
    

    1.3 Location

    • 代表当前浏览器的地址信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
    • 如果直接打印location,则可以获取当前页面完整路径
    alert(location);
    
    • 如果直接将location属性修改为一个完整的路径,或相对路径,则我们页面会自动跳转到该路径,并会生成相应的历史记录
    location="http://www.baidu.com";
    location="01.BOM.html";
    

    assign():用来跳转到其他页面,作用和直接修改location一样

    location.assign("http://www.baidu.com");
    

    reload():重新加载当前页面,作用和刷新按钮一样

    ctrl+F5:强制清空缓存刷新
    reload(true):强制清空缓存刷新

    location.reload();
    location.reload(true);
    

    replace():跳转页面,但不会生成历史记录,不能使用回退按钮回退

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

    1.4 History

    • 代表浏览器的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时有效
    • history.length:可以获取到当前访问的链接数量
    • history.back():回退到上一个页面,作用和浏览器的回退按钮一样
    • history.forward():跳转下一个页面,作用和浏览器的前进按钮一样
    • history.go():跳转到指定页面,需要一个整数作为参数,正数向前,负数向后

    1.5 Screen

    • 代表用户的屏幕信息,通过该对象可以获取到用户的显示器的相关信息

    2. 定时器

    2.1 定时调用

    setInterval()

    • 定时调用
    • 可以将一个函数每隔一段时间执行一次
    • 参数:
      • 回调函数
      • 每次调用间隔的时间,单位是毫秒
    • 返回值:
      • 返回一个数字,作为定时器的唯一标识

    clearInterval()

    • 关闭定时器
    • 可以接受任何参数,有效则停止定时器,无效则什么也不做
    var num=1;
    var timer=setInterval(function(){
    	count.innerHTML=num++;
    	if(num==11){
    		clearInterval(timer);
    	}
    },100);
    

    2.2 延时调用

    setTimeout()

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

    clearTimeout()

    • 关闭一个延时调用
    var timer=setTimeout(function(){
    	console.log(num++);
    },3000)
    
    clearTimeout(timer);
    

    切换图片练习

    var img1=document.getElementById("img1");
    var imgArr=["img/1.jpg","img/2.jpg","img/3.jpg","img/4.jpg","img/5.jpg","img/6.jpg"]
    var index=0;
    var timer;
    btn01.onclick=function(){
    	//在开启定时器之前,需要将当前元素上的其他定时器关闭
    	clearInterval(timer);
    	
    	timer=setInterval(function(){
    	index++;
    	index%=imgArr.length)
    	img1.src=imgArr[index];
    	},1000);
    }
    btn02.onclick=function(){
    	clearInterval(timer);
    }
    
    

    3. 类的操作

    • 通过style属性来修改元素的样式,每修改一个样式,浏览器就要重新渲染一次页面,这样的执行性能是比较差的,要修改多个样式时,也不太方便
    • 我们可以通过修改元素的class属性来间接修改样式,这样只要修改一次即可同时修改多个样式,浏览器只需重新渲染页面一次。并且这种方式可以使表现和行为进一步分离
    function addClass(obj,cn){
    	if(!hasClass(obj,cn)){
    		obj.className+=" "+cn;
    	}
    }
    // 判断一个元素中是否含有指定的class属性值
    function hasClass(obj,cn){
    	var reg=new RegExp("\\b"+cn+"\\b");
    	return reg.test(obj.className);
    }
    //删除一个元素中的指定的class属性
    function removeClass(obj,cn){
    	var reg=new RegExp("\\b"+cn+"\\b");
    	obj.className=obj.className.replace(reg,"");
    }
    //切换一个类
    //如果元素中具有该类,则删除;如果元素中没有该类,则添加
    function toggleClass(obj,cn){
    	if(hasClass(obj,cn)){
    		removeClass(obj,cn);
    	}else{
    		addClass(obj,cn);
    	}
    }
    

    4. JSON

    4.1 JSON简介

    • JS的对象只有JS自己认识,其他语言都不认识
    • JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互
    • JSON
      • JavaScript Object Notation JS对象表示法
      • JSON和JS对象的格式一样,只不过JSON字符串中属性名必须加双引号

    4.2 JSON分类

    对象{}

    var obj='{"name":"ljw","age":25,"gender":"女"}';
    

    数组[]

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

    4.3 JSON中允许的值

    • 字符串
    • 数值
    • 布尔值
    • null
    • 对象
    • 数组

    4.4 将JSON字符串转换为JS对象

    JSON.parse()

    var json='{"name":"ljw","age":25,"gender":"女"}';
    var o=JSON.parse(json);
    

    4.5 将JS对象转换为JSON字符串

    JSON.stringify()

    var obj={"name":"ljw","age":25,"gender":"女"};
    var str=JSON.stringify(obj3);
    

    4.7 解决JSON在IE7及以下无效的情况

    eval()

    • 这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回
    • 如果使用eval()执行的字符串中含有{},它会将{}当成是代码块,需要在字符串前后各加一个()
    • 在开发中尽量不要使用,性能较差,且具有安全隐患
    var str="alert('hello');";
    var obj=eval("("+str+")");
    

    4.8 终极解决办法

    • 引入外部json2.js文件,该文件新建了一个JSON对象
    <script type="text/javascript" src="js/json2.js"></script>
    

    你可能感兴趣的:(前端,javascript)