()# JS基础知识梳理
JS学习一段时间后的回顾
概述
- 定义:运行在客户端的脚本语言(不需要编译,JS引擎逐行解释执行)
- 浏览器的两部分:渲染引擎(内核,解析HTML和CSS)、JS引擎(解析JS,如V8)
- JS组成:ECMAScript(编程语法和基础核心)、DOM(文档对象模型)、BOM(浏览器对象模型)
变量
- 存放数据的容器
- 声明变量+赋值:var
- 赋值更新覆盖,声明多个变量逗号隔开,只声明不赋值是undefined、不声明不赋值报错、不声明只赋值可以使用变成全局。
- 数据类型:根据占用空间的不同划分数据类型,JS变量根据等号后面的数据确定数据类型切可以变化。
- 简单数据类型:Number(IsNaN)、string(length)、 Boolean、undefined (声明变量没赋值)、null(空值)。typeof var 查看变量类型
- 类型转换:
- 转换为字符串:变量.toString()、强制转换:String(变量)、隐式转换:加号拼接;
- 转换为数字型:把字符串转换为整数parseInt(变量)、把字符串转换为浮点数parseFloat(变量)、强制转换Number()、隐式转换:用-/*运算
- 转换为布尔型:Boolean(),表示NaN、null、’’、undefined转化为false
- 数组:一组数据存在一个变量值下,逗号分隔,数组元素类型没限制,元素索引号从0开始
- 新增元素:改变数组长度;追加数组索引号;
运算符
- 算数运算符:
+-*/%
- 比较运算符:
<>= == != === !==
- 逻辑运算符:
&& || !
会有逻辑中断,影响计算结果 - 赋值运算符:
= += -= %= /=
流程控制
- if else 和switch 的区别
- 循环的选取:次数相关用for,while和dowhile可以做更复杂的判断
- continue是跳出本次循环,继续进入下一循环;break是直接跳出循环
函数
- 重复调用执行的一段代码
- 形参默认值是undefined
- 没有return时函数的返回值是undefined
- 伪数组arguments存储了函数的实参,可以用length属性,但不能pop或push
作用域
- 定义:变量在某 个范围内起作用,减少命名冲突,提高程序可靠性
- ES6 前:函数内部是局部作用域,一个单独js文件内的是全局作用域(函数内部不声明直接赋值的变量也是全局变量),全局变量在浏览器关闭的时候才会销毁。
- ES6新增块级作用域
- 内部函数可以访问外部函数的变量,链式查找,就近原则。
- JS代码运行分为预解析和代码执行两部分,预解析把所有的var和function提到当前作用域前面(变量解析把变量声明提升,不提升赋值,所以在变量声明赋值前打印是undefined)
var a=b=c=9;
里面b和c都没有声明- 对象声明方式:字面量,
new Object()
, 构造函数。用for in 遍历对象属性 - Math对象不是构造函数,直接调用就可以。
+new Date()
可以直接返回毫秒数,H5中直接采用Date.now()
,计算时间差应当用时间戳相减再转化为时分秒- 检测是否为数组的方法 1.
instanceof
2.Array.isArray()
- 添加、删除数组:1. push 在数组末尾添加一个或多个,返回值为新数组长度;2. unshift在数组头部添加一个或多个,返回数组长度;3. pop 删除数组最后一个数,不加参数,返回删除的元素;4. shift: 删除第一个数,返回删除的元素,不带参数
- 数组排序sort使用
arr.sort(function(a,b){
return a-b; //升序
})
- 数组去重:(利用indexOf)
var newArr = [];
for (var i = 0; i < oldArr.length; i++) {
if (newArr.indexOf(arr[i]) === -1 ) {
new.Arr.push(arr[i]);
}
}
- 数组转换为字符串:
arr.toString()
、join(分隔符)
- 数组常用方法:concat\slice\splice
- 基本包装类型:把简单数据类型包装为复杂数据类型,可以获取length属性。原理是新建临时变量然后赋值再销毁
- 字符串里面的的值不变,更改只是改变地址指向,原来的值内存还是没有销毁,字符串的操作都会返回一个新的字符串。所以,避免大量的拼接和赋值字符串。
- 根据位置找字符:Arr.charAt(i)或者H5新增的str[i]; 判断用户用了哪个键:charCodeAt(),返回ASCII码
- 字符串截取:substr(start, lenght)、slice(start, end);替换str.replace(‘被替换’,‘替换 ’);字符串转换成数组split();
- 简单数据类型为值类型,直接存在栈里面,实参传递给形参互不干扰;复杂类型是引用类型,在栈中存放地址,实际的值存在堆里,所以函数传参的时候传的是地址操作同一个对象,会相互影响
BOM&DOM(WebAPI)
- API 应用程序编程接口;WebAPI是一套操作浏览器功能和页面元素的API,W3C标准
- DOM文档对象模型,处理HTML的接口,改变页面内容结构样式。 ** DOM把文档、元素、节点都看做是对象,有自己的属性和方法**
- DOM获取页面元素
- 根据ID获取
document.getElementByID()
- 根据标签名获取
document.getElementsByTagName()
返回值是伪数组,可以用element.getElementsByTagName()
- 根据类名获取(H5新增)
document.getElementsByClassName()
- H5新增querySelector(),querySelectorAll()不区分选择器,只得到第一个元素
- 获取body:document.body
- 获取html:document.documentElement
- 节点获取元素:( 利用节点层次获取)
- 父子兄:parentNode、children、previousElementSilbing
- 添加创建删除元素节点:
- 创建:document.write() 很少使用,会导致页面重绘; document.createElement();ele.innerHTML() 多个字符拼接字符串时速度会慢,但是用数组拼接的时候效率很高
- 添加:node.appendChild(child)、node.insertBefore(child,子元素)
- 删除:node.removeChild(child)
- 克隆:node.cloneNode(),参数为true是深拷贝,false和空是浅拷贝
- 改变节点:
- 改变元素内容:innerText(去除html标签和空格换行)、innerHTML,两个属性均可读写
- 改变属性:src、href、id、alt、title
- 改变样式:ele.style.属性、ele.className(会覆盖),属性是驼峰命名法
- 事件:触发-响应机制,由事件源、事件类型、事件处理程序(函数赋值)
注册事件:
- 传统注册方式:ele.onclick,具有唯一性,后面会覆盖前面
- 方法监听事件:target.addEventLisener(type,listener),依次执行不覆盖,可以添加多个监听器
解绑事件: - 传统方式:ele.onclick = null
- 监听方式: eventTarget.removeEventListener(type,listener)
DOM事件流:
从上到下捕获-从下到上冒泡
事件对象e: - 一般做形参
- 有了事件才会存在,是系统自动创建的,不需要传递参数
- 包含一系列的相关数据集合
- ie678中用window.event
- 常用属性:e.target(谁触发就返回谁)、e.type(事件类型)、e.preventDefault()(阻止默认行为)、e.stopPropagation()(阻止冒泡)
- 常见鼠标事件属性:e.clientX,e.clientY,e.pageX,e.pageY
- 常用键盘事件:onkeyup、onkeydown、onkeypress(不识别功能键,区分大小写);属性:keyCode
事件委托: - 不给子节点单独设置事件监听器,设置在父结点上,用事件冒泡影响子节点
- 获取属性值
- ele.属性名:元素的内置属性
- ele.getAttribute(‘属性’):自定义属性,通过setAtrribute设置,通过removeAtrribute删除
自定义属性的目的是保存数据方便使用。在H5中规定自定义属性加上data-前缀,可以通过ele.dataset.index获取
- BOM是浏览器对象模型,提供浏览器窗口交互的对象,各厂商定义的,兼容性较差。window对象是浏览器顶级对象,即是接口,又是全局对象。
- 常见事件:window.onload(只能写一次,会覆盖,最好用监听方式。load是等页面全部内容加载完毕才才执行)、onsize、pageshow
- 定时器:window.
- setTimeout(调用函数,延迟时间毫秒)只调用一次;clearTimeout(定时器名)
- setInterval(回调函数,间隔时间)反复调用;clearInterval(定时器名)
- this指向:
- 全局作用域、普通函数和定时器中的this指向window
- 方法调用中指向调用者
- 构造函数指向实例
- JS执行机制
同步任务在执行栈中,回调函数当作异步任务处理,先提交给异步进程处理,触发时放到任务队列中,执行栈不断检测任务队列(事件循环) - window的location对象:属性href、search、host、port、pathname、search、hash,方法:assign重定向、replace(跳转,不记录浏览历史)、reload(刷新重载)
- window的navigator对象:常用属性:userAgent(判断浏览器型号)
- window的history对象:方法:back()、forward()、go(参数)
网页特效
- 元素offset系列:动态得到元素的位置和大小、只读
- 获取相对于定位父元素的偏移:ele.offsetTop…、ele.offsetParent(返回带有定位的父节点)
- 获取元素的大小:ele.offsetWidth、ele.offsetHeight,包含padding和边框
- 和style的区别:style只能获取行内样式、获取数值带有单位、可读可写
- 元素可视区client系列:动态获取元素边框大小,元素大小,不包括边框
- 元素滚动scroll系列:scrollWidth…滚动内容大小,被卷的距离(ele.scrollTop…页面滚动距离window.pageYOffset)
- 立即执行函数:不需要调用,独立创建了一个作用域,里面都是局部变量,不会命名冲突。
- (function(){})()
- 移动端事件:touchstart、touchmove、touchend、transitionend,可以大量选用CSS3的特效不存在兼容问题
- 移动端的click事件有300ms延时,可以通过禁用缩放或者fastclick插件解决问题
ES5新增
- 数组方法:
- forEach(func(value,index,arr))遇到return不会终止迭代
- map()
- filter(func(value,index,arr)),返回符合要求的新数组
- some(),返回布尔值,是否存在满足条件的值,找到一个满足的就不继续了
- every()
- 字符串方法
- trim 去掉两端空白字符
- 对象方法
- obj.keys 获取全部属性名,数组的形式
- obj.defineProperty(obj,prop,description{value,writable,enumerable,configurable})添加更改属性
- 严格模式 use strict
- 变量必须先声明再调用,不能删除声明好变量
- 全局作用域定义的函数this指向不是window是undefined
- 构造函数不可以不通过new调用(this会出错)
- 定时器函数的this还是指向window
- 函数内不可以有重名参数
- 函数写在最顶层,非函数代码块中不能声明函数
函数
- 函数定义 函数都是Function对象的实例
- 命名函数 function fn(){}
- 匿名函数 var fun= function() {}
- new Function (prop1, prop2,函数体)字符串形式
- 函数调用:
- 普通函数:this指向window
- 对象的方法: this指向对象
- 构造函数: this指向实例对象,原型对象的方法this指向的也是实例对象
- 绑定事件函数:this指向函数调用者
- 定时器函数:this指向window
- 立即执行函数:this指向window
- this指向改变:
- fn.call() 调用函数,主要用于实现继承
- fn.apply(this指向,[参数]) 调用函数,主要应用于对数组的math对象操作(如Math.max.apply(Math,arr))
- fn.bind(thisArg,arg1…) 不调用,只绑定,返回一个改变this的新班函数
- 高阶函数(接收函数或者返回函数)
- 闭包: 有权访问另一个函数作用域的函数,闭包可以返回一个函数,是高阶函数。闭包作用:延伸变量作用范围。立即执行函数就是一个闭包
- 深浅拷贝:浅拷贝是拷贝引用(地址),修改会相互影响
本地存储
- 数据存储在用户浏览器中,读取方便,页面刷新不丢失、只能使用字符串
- window.sessionStorage: setItem、getItem、removeItem、clear
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
- localStorage:
- 生命周期永久存在,除非手动删除
- 多窗口共享
- 键值对存储使用
面向对象
- 特性: 封装性、继承性、多态性
- 类:
- 构造函数constructor(),实例化的时候直接调用,类中函数直接写
- 继承父类extends,在constructor中用super()调用父类的构造函数(super要写在this之前),用super.func()调用父类的普通函数
- 必须先定义类才能通过类实例化对象
- 类中共有的属性方法必须加this使用
- constructor里面的this指向实例化对象,类函数的this指向函数调用者
- 构造函数:用function创建对象,函数名首字母大写、用new实例化
- 实例成员:函数内部通过this添加的成员,实例化成员访问
- 静态成员:在构造函数本身添加的成员,只能通过构造函数访问
- 构造函数的原型属性prototype,用于共享方法,避免多实例的内存浪费
- 对象的__proto__指向构造函数原型prototype,二者等价
- 对象实例的__proto__指向一个原型,逐层向上形成原型链,方法在原型链上逐层查找
- 原型对象和构造函数里面的this都指向实例对象
- fun.call(thisArg, arg1…),改变this指向,调用函数
推荐写法
- 引号推荐单引号
- 用浏览器调试工具的source打断点,刷新网页,watch监视来调试JS
- 标识符起名一般有意义,变量用名词,函数用动词
- 移动端轮常见效果插件:Swiper、superslide、iscroll