JS
JavaScript 的组成
- ECMAScript - 语法规范
- 变量、数据类型、类型转换、操作符
- 流程控制语句:判断、循环语句
- 数组、函数、作用域、预解析
- 对象、属性、方法、简单类型和复杂类型的区别
- 内置对象:Math、Date、Array,基本包装类型String、Number、Boolean
- Web APIs
- BOM
- onload页面加载事件,window顶级对象
- 定时器
- location、history
- DOM
- 获取页面元素,注册事件
- 属性操作,样式操作
- 节点属性,节点层级
- 动态创建元素
- 事件:注册事件的方式、事件的三个阶段、事件对象
- BOM
变量
变量是计算机内存中存储数据的标识符,根据变量名称可以获取内存中存储的数据。
驼峰命名法。
数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。引用数据类型:对象(Object)、数组(Array)、函数(Function)。
简单类型和复杂类型的区别
基本类型又叫做值类型,复杂类型又叫做引用类型
值类型:简单数据类型,基本数据类型,在存储时,变量中存储的是值本身,因此叫做值类型。
引用类型:复杂数据类型,在存储是,变量中存储的仅仅是地址(引用),因此叫做引用数据类型。
-
堆和栈
堆栈空间分配区别: 1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。 2、堆(操作系统): 存储复杂类型(对象),一般由程序员分配释放, 若程序员不释放,由垃圾回收机制回收。
数据类型转换
转换成字符串类型
-
toString()
var num = 5; console.log(num.toString()); -
String()
String()函数存在的意义:有些值没有toString(),这个时候可以使用String()。比如:undefined和null -
拼接字符串方式
num + "",当 + 两边一个操作符是字符串类型,一个操作符是其它类型的时候,会先把其它类型转换成字符串再进行字符串拼接,返回字符串
转换成数值类型
-
Number()
Number()可以把任意值转换成数值,如果要转换的字符串中有一个不是数值的字符,返回NaN -
parseInt()
var num1 = parseInt("12.3abc"); // 返回12,如果第一个字符是数字会解析知道遇到非数字结束 var num2 = parseInt("abc123"); // 返回NaN,如果第一个字符不是数字或者符号就返回NaN -
parseFloat()
parseFloat()把字符串转换成浮点数 parseFloat()和parseInt非常相似,不同之处在与 parseFloat会解析第一个. 遇到第二个.或者非数字结束 如果解析的内容里只有整数,解析成整数 -
+,-0等运算
var str = '500'; console.log(+str); // 取正 console.log(-str); // 取负 console.log(str - 0);
转换成布尔类型
- Boolean()
0 ''(空字符串) null undefined NaN 会转换成false 其它都会转换成true
运算符的优先级
优先级从高到底
1. () 优先级最高
2. 一元运算符 ++ -- !
3. 算数运算符 先* / % 后 + -
4. 关系运算符 > >= < <=
5. 相等运算符 == != === !==
6. 逻辑运算符 先&& 后||
7. 赋值运算符
程序三种结构
- 顺序结构
- 分支结构 if else、switch case
- 循环结构 while、do..while、for循环
调试
- 过去调试JavaScript的方式
- alert()
- console.log()
- 断点调试
- 调试中的相关操作
Watch: 监视,通过watch可以监视变量的值的变化,非常的常用。
F10: 程序单步执行,让程序一行一行的执行,这个时候,观察watch中变量的值的变化。
F8:跳到下一个断点处,如果后面没有断点了,则程序执行结束。
函数
把一段相对独立的具有特定功能的代码块封装起来,形成一个独立实体,就是函数 函数的作用就是封装一段代码,可以重复使用
arguments的使用
JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。也就是说所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有的实参。arguments是一个伪数组,因此及可以进行遍历
匿名函数
匿名函数:没有名字的函数
匿名函数如何使用:
将匿名函数赋值给一个变量,这样就可以通过变量进行调用
匿名函数自调用
自调用函数
匿名函数不能通过直接调用来执行,因此可以通过匿名函数的自调用的方式来执行
(function () {
alert(123);
})();
函数是一种数据类型
function fn() {}
console.log(typeof fn);
- 函数作为参数
因为函数也是一种类型,可以把函数作为两一个函数的参数,在另一个函数中调用
- 函数做为返回值
因为函数是一种类型,所以可以把函数可以作为返回值从函数内部返回。
块级作用域
任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。
作用域链
只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
预解析
JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程
预解析过程:
- 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
- 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。
- 先提升var,在提升function。
变量提升
-
变量提升
定义变量的时候,变量的声明会被提升到作用域的最上面,变量的赋值不会提升。
-
函数提升
JavaScript解析器首先会把当前作用域的函数声明提前到整个作用域的最前面
对象
new关键字
new在执行时会做四件事情
new会在内存中创建一个新的空对象
new会让this指向这个新的对象
执行构造函数 目的:给这个新对象加属性和方法
new会返回这个新对象
this详解
- 函数在定义的时候this是不确定的,只有在调用的时候才可以确定
- 一般函数直接执行,内部this指向全局window
- 函数作为一个对象的方法,被该对象所调用,那么this指向的是该对象
- 构造函数中的this其实是一个隐式对象,类似一个初始化的模型,所有方法和属性都挂载到了这个隐式对象身上,后续通过new关键字来调用,从而实现实例化
创建对象的四种方式
- 对象字面量
- 通过构造函数Object()来创建
- 工厂函数
- 自定义构造函数
// 自定义构造函数
// 帕斯卡命名 第一个单词的第一个字母大写,后续每一个单词的第一个字母都大写
// for in 可以遍历对象的成员
let obj = {
name: 'zs',
age: 18,
sex: '男',
sayHi: function() {
console.log(this.name + ':hello');
}
}
// 输出对象属性和值
for(let key in obj) {
console.log(key + '---' + obj[key]);
}
// 删除对象
delete obj.name;
内置对象
JavaScript中的对象分为3种:内置对象、自定义对象、浏览器对象
JavaScript 提供多个内置对象:Math/Array/Date....
数组
-
创建数组对象的两种方式
- 字面量方式
- new Array()
-
检测一个对象是否是数组
- instanceof
- Array.isArray() HTML5中提供的方法,有兼容性问题
函数的参数,如果要求是一个数组的话,可以用这种方式来进行判断
-
toString()/valueOf()
- toString() 把数组转换成字符串,逗号分隔每一项
- valueOf() 返回数组对象本身
-
数组常用方法
push()、shift()、unshift()、reverse()、sort()、splice()、indexOf()
数组常用方法
栈操作:先进后出
- push() 向数组插入元素
- pop() 取出数组最后一个元素
队列操作:先进先出
- push() 向数组插入元素
- shift() 取出数组第一个元素
- unshift() 插入一个元素到数组首位
排序方法:
- reverse() 翻转数组,(第 i 个和第 length - i - 1个进行交换)
- sort() 对数组排序,默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的
操作方法:
- concat() 把参数拼接到当前数组
- slice(start,end) 截取新数组
- splice() 插入/删除/替换当前数组某些项目
- join('-') 用参数拼接字符串
// 清空数组:
let arr = [1,2,3];
arr = []; // 第一种(推荐)
arr.length() = 0; //第二种
// 第一个参数,从什么位置开始删除 索引
//第二个参数 ,删除多少个元素
arr.splice(0,arr.length);
// 1-2-3
arr.join("-");
位置方法:
- indexOf() //如果没找到返回-1
- lastIndexOf() //如果没找到返回-1
迭代方法:自带循环;html5中提供
- every()
- filter()
- forEach()
- map()
- some()
字符串常用方法
基本包装类型
基本类型包装成复杂类型 String Number Boolean (一般情况下不会使用Number Boolean 基本包装类型)
PrimitiveValue 原始值
字符串不可变
给字符串重新赋值,内存要重新分配空间
字符串的所有方法都不会修改原始字符串本质(字符串不可变性)
字符串的方法
// 1 字符方法
charAt() //获取指定位置处字符
charCodeAt() //获取指定位置处字符的ASCII码
str[0] //HTML5,IE8+支持 和charAt()等效
// 2 字符串操作方法
concat() //拼接字符串,等效于+,+更常用
slice() //从start位置开始,截取到end位置,end取不到
substring() //从start位置开始,截取到end位置, end取不到
substr() //从start位置开始,截取length个字符
// 3 位置方法
indexOf() //返回指定内容在元字符串中的位置
lastIndexOf() //从后往前找,只找第一个匹配的
// 4 去除空白
trim() //只能去除字符串前后的空白
// 5 大小写转换方法
to(Locale)UpperCase() //转换大写
to(Locale)LowerCase() //转换小写
// 6 其它
search()
replace()
split()
去除字符串中的空白
let s = ' sa afa ag 1 3';
let arr = s.split(" ");
console.log(arr);
console.log(s.trim());
//split() 配合 join() 取出空白 ;trim()只能去除数组前后空白
console.log(arr.join(""));
求字符串中次数出现最多的字符和次数
// 求字符串中次数出现最多的字符和次数
let s = "afavaooaogjvoagaj";
// 最大值的字符
let ch;
// 统计最大值
let num;
// 记录字符串中每一个字符出现的次数
let o = {};
for (let i = 0; i < s.length; i++) {
let item = s.charAt(i);
if (o[item]) {
// 对象中有该属性
o[item]++;
} else {
// 对象中没有该属性
o[item] = 1;
}
}
// 假设最大值是1
num = 1;
for (let key in o) {
if (num < o[key]) {
num = o[key];
ch = key;
}
}
console.log(num);
console.log(ch);
获取url中的参数
let url = 'https://www.bilibili.com/login?name=zs&age=18&a=1&b=2';
let o = {};
function getParams(url) {
let index = url.indexOf('?') + 1;
let params = url.substr(index);
let arr = params.split('&');
for (let i = 0; i < arr.length; i++) {
let tmpArr = arr[i].split('=');
let key = tmpArr[0];
let value = tmpArr[1];
o[key] = value;
}
return o;
}
let obj = getParams(url);
console.log(obj);
console.log(obj.name);
DOM
DOM是文档对象模型:当网页被加载时,浏览器会创建页面的文档对象模型。
- 文档:一个网页可以称为文档
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等)
- 元素:网页中的标签
- 属性:标签的属性
DOM经常进行的操作
- 获取元素
- 对元素进行操作(设置其属性或调用其方法)
- 动态创建元素
- 事件(什么时机做相应的操作)
根据id获取元素
var div = document.getElementById('main');
console.log(div);
// 获取到的数据类型 HTMLDivElement,对象都是有类型的
根据标签名获取元素
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
console.log(div);
}
根据name获取元素*
var inputs = document.getElementsByName('hobby');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
console.log(input);
}
根据类名获取元素*
var mains = document.getElementsByClassName('main');
for (var i = 0; i < mains.length; i++) {
var main = mains[i];
console.log(main);
}
根据选择器获取元素*
var text = document.querySelector('#text');
console.log(text);
var boxes = document.querySelectorAll('.box');
for (var i = 0; i < boxes.length; i++) {
var box = boxes[i];
console.log(box);
}
自定义属性操作
- getAttribute() 获取标签行内属性
- setAttribute() 设置标签行内属性
- removeAttribute() 移除标签行内属性
- 与element.属性的区别: 上述三个方法用于获取任意的行内属性。
样式操作
- 使用style方式设置的样式显示在标签行内
var box = document.getElementById('box');
box.style.width = '100px';
box.style.height = '100px';
box.style.backgroundColor = 'red';
-
注意
通过样式属性设置宽高、位置的属性类型是字符串,需要加上px
类名操作
- 修改标签的className属性相当于直接修改标签的类名
var box = document.getElementById('box');
box.className = 'show';
创建元素的三种方式
document.write()
document.write('新设置的内容<p>标签也可以生成</p>'); //当点击单击按钮事件时,会把之前整个页面覆盖掉。
innerHTML
var box = document.getElementById('box');
box.innerHTML = '新内容<p>新标签</p>';
// 优化1
let datas = ['西施', '貂蝉', '陈雨', '落雁'];
let box = document.getElementById('box');
let btn = document.getElementById('btn');
btn.onclick = function () {
let html = '<ul>';
for (let i = 0; i < datas.length; i++) {
let data = datas[i];
html += '<li>' + data + '</li>';
}
html += '</ul>';
box.innerHTML = html;
}
// 优化2 性能最高
let datas = ['西施', '貂蝉', '陈雨', '落雁'];
let box = document.getElementById('box');
let btn = document.getElementById('btn');
btn.onclick = function () {
let array = [];
array.push('<ul>')
for (let i = 0; i < datas.length; i++) {
let data = datas[i];
array.push('<li>' + data + '</li>');
}
array.push('</ul>');
box.innerHTML = array.join(''); //当li生成页面后,再从页面上查找li注册事件
}
document.createElement()
var div = document.createElement('div'); //内存中动态创建一个元素,页面上没有
document.body.(div); //放在页面上
节点属性
- nodeType 节点的类型
- 1 元素节点
- 2 属性节点
- 3 文本节点
- nodeName 节点的名称(标签名称)
- nodeValue 节点值
- 元素节点的nodeValue始终是null
节点层级
var box = document.getElementById('box');
console.log(box.parentNode); //父节点
console.log(box.childNodes); //子节点集合
console.log(box.children); //获取子元素节点集合
console.log(box.nextSibling); //下一个兄弟节点
console.log(box.previousSibling); //上一个兄弟节点
console.log(box.nextElementSibling); //下一个兄弟元素
console.log(box.previousElementSibling); //上一个兄弟元素
console.log(box.firstChild); //获取第一个节点
console.log(box.lastChild); //获取最后一个节点
console.log(box.firstElementChild); //返回第一个子元素
console.log(box.lastElementChild) //返回最后一个子元素
-
注意
childNodes和children的区别,childNodes获取的是子节点,children获取的是子元素
nextSibling和previousSibling获取的是节点,获取元素对应的属性是nextElementSibling和previousElementSibling获取的是元素
nextElementSibling和previousElementSibling有兼容性问题,IE9以后才支持
-
总结
节点操作,方法
appendChild()
insertBefore()
removeChild()
replaceChild()
节点层次,属性
parentNode
childNodes
children
nextSibling/previousSibling
firstChild/lastChild
事件
事件:触发-响应机制
事件三要素
- 事件源:触发(被)事件的元素
- 事件名称: click 点击事件
- 事件处理程序:事件触发后要执行的代码(函数形式)
事件的基本使用
var box = document.getElementById('box');
box.onclick = function() {
console.log('代码会在box被点击后执行');
};
注册/移除事件的三种方式
var box = document.getElementById('box');
// 无法给同一个对象的同一个事件注册多个事件处理函数
box.onclick = function () {
console.log('点击后执行');
};
box.onclick = null;
// 可以给同一个对象的同一个事件注册多个事件处理函数,有浏览器兼容性问题,IE9以后才支持
box.addEventListener('click', eventCode, false);
// 想要移除事件,注册事件的时候不能使用匿名函数(要给函数命名)
box.removeEventListener('click', eventCode, false);
// IE9以前特有方法
box.attachEvent('onclick', eventCode);
box.detachEvent('onclick', eventCode);
function eventCode() {
console.log('点击后执行');
}
兼容代码
function addEventListener(element, type, fn) {
if (element.addEventListener) {
element.addEventListener(type, fn, false);
} else if (element.attachEvent){
element.attachEvent('on' + type,fn);
} else {
element['on' + type] = fn;
}
}
function removeEventListener(element, type, fn) {
if (element.removeEventListener) {
element.removeEventListener(type, fn, false);
} else if (element.detachEvent) {
element.detachEvent('on' + type, fn);
} else {
element['on'+type] = null;
}
}
事件的三个阶段
-
捕获阶段
-
当前目标阶段 (执行当前点击的事件,attachEvent()只有这个阶段)
-
冒泡阶段(子元素和父元素都定义了事件,当触发子元素的事件时,父元素的事件也会触发)
阻止事件传播的方式
- 标准方式 event.stopPropagation(); 取消冒泡
- IE低版本 event.cancelBubble = true; 标准中已废弃
事件对象的属性和方法
-
event.type 获取事件类型
-
事件对象.eventPhase属性可以查看事件触发时所处的阶段
-
clientX/clientY 所有浏览器都支持,窗口位置
-
pageX/pageY IE8以前不支持,页面位置,滚动条
-
event.target || event.srcElement 用于获取触发事件的元素
-
event.currtentTarget 真正点击的元素
-
event.preventDefault() 取消默认行为 (相当 return false;)
-
事件对象.offsetLeft , 事件对象.offsetTop 获取盒子在页面上的位置
-
event.keycode 键盘码 0 - 18,9 - 57 后退键 - 8 可用于处理文本输入只能是数字
常用的鼠标和键盘事件
- onmouseup 鼠标按键放开时触发
- onmousedown 鼠标按键按下触发
- onmousemove 鼠标移动触发
- onkeyup 键盘按键按下触发
- onkeydown 键盘按键抬起触发
BOM
BOM(Browser Object Model) 是指浏览器对象模型,浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。BOM由多个对象组成,其中代表浏览器窗口的Window对象是BOM的顶层对象,其他对象都是该对象的子对象。
对话框
- alert(message)
- prompt(text,defaultText)
- confirm(message)
页面加载事件
- onload
window.onload = function () {
// 当页面加载完成执行
// 当页面完全加载所有内容(包括图像、脚本文件、CSS 文件等)执行
// 不仅是window有,元素也有onload属性
// f5 先卸载页面 在 重新加载页面
}
- onunload
window.onunload = function () {
// 在onunload中所有对话框都无法使用 window对象被冻结
// 当用户退出页面时执行
}
定时器
setTimeout()和clearTimeout()
在指定的毫秒数到达之后执行指定的函数,只执行一次
// 创建一个定时器,1000毫秒后执行,返回定时器的标示
var timerId = setTimeout(function () {
console.log('Hello World');
}, 1000);
// 取消定时器的执行
clearTimeout(timerId);
setInterval()和clearInterval()
定时调用的函数,可以按照给定的时间(单位毫秒)周期调用函数
// 创建一个定时器,每隔1秒调用一次
var timerId = setInterval(function () {
var date = new Date();
console.log(date.toLocaleTimeString());
}, 1000);
// 取消定时器的执行
clearInterval(timerId);
URL统一资源定位符 (Uniform Resource Locator)
- URL的组成
scheme://host:port/path?query#fragment
http://www.itheima.com:80/a/b/index.html?name=zs&age=18#bottom
scheme:通信协议
常用的http,ftp,maito等
host:主机
服务器(计算机)域名系统 (DNS) 主机名或 IP 地址。
port:端口号
整数,可选,省略时使用方案的默认端口,如http的默认端口为80。
path:路径
由零或多个'/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。
query:查询
可选,用于给动态网页传递参数,可有多个参数,用'&'符号隔开,每个参数的名和值用'='符号隔开。例如:name=zs
fragment:信息片断
字符串,锚点.
history对象
- back()
- forward()
- go() go(-1) 后退 go(1) 前进
navigator对象
- userAgent userAgent 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代理头的值。
偏移量
- offsetParent用于获取定位的父级元素
- offsetParent和parentNode的区别