JavaScript 知识点
本文是从简书复制的, markdown语法可能有些出入, 想看"正版"和更多内容请关注 简书: 小贤笔记
JS基础
- 页面由三部分组成:
- html:超文本标记语言,负责页面结构
- css:层叠样式表,负责页面样式
- js:轻量级的脚本语言,负责页面的动效和数据交互
小总结:结构,样式和行为,三者相分离 - 在html页面中写结构
- 通过 link标签的href属性,引入css样式
- 通过script标签的src属性,引入js脚本
- css引入页面的方式有三种
- 行内
<div style="width:200px;height:300px;"></div>
- 内嵌:在header里面写一个
<style>选择器{key:value}</style>
- 外链:在header里面写一个
<link rel="stylesheet" href="css/index.css"/>
- 行内
- JS引入页面的方式,同CSS相似
- 内嵌:在开发过程中,建议把script放在body底部;如果非要把script标签对,放在head里面的话;需要加window.onload
window.onload=function(){ document.body.innerHTML='XXXXXX'; }
- 行内:
<div onclick="xxxx" onmouseover="xxxx"></div>
- 外链:
<script src="01.js"></script>
注意:如果script作为JS的外链,一定不要在两个script标签中写代码,写了也没用
- 属性和方法的区别:属性没括号,方法有括号
- 字符串和变量的区别:字符串有引号,变量没引号
- 字符串一般用单引号;为了元素身跟上的属性值区分开来;属性值一般是""
- 变量,就是别名;var str; 告诉浏览器,定义了str这么一个变量
- 如果没有定义变量,xxx is not defined
- JS常见的输出方式7种
- alert('') ; 显示带有一条指定消息和一个 OK 按钮的警告框
- confirm('确定要删除?'); 他有两个返回值:true 真, false假
- console.log(''); 可以在控制台打印出我们想要打印的内容
- console.dir(); 打印出对象身上的属性和方法
- document.write() 向文档写入 HTML 表达式或 JavaScript 代码
如果遇到window.onload会清空页面 - 元素.innerHTML=xxxx 设置或返回表格行的开始和结束标签之间的 HTML
- console.table(); 可以把数组和对象,以表格的形式打印出来
var ary2=[ { name:'a', age:1, sex:'gril' }, { name:'王b', age:2, sex:'boy' } ]; console.table(ary2);
- chrome控制台
- Elements:用来调试html+css的
- console:用来调试JS的
- sources:可以拿到该网站相关的资源:images ,html ,css, js
体验JS编程思想
-
需求:鼠标移入div1的时候,div2显示;鼠标移出div1的时候,div2隐藏
-
实现思路:
- 高度:div2的高度为0; 移入div1后高度为100;移出div1时div2高度0;
- display:block显示,none,隐藏;
- 透明度:rgba(); opacity();
- 定位:left和top;
- margin:margin-left和 margin-top;
- overflow:hidden和visible;
-
JS获取元素的方式:
- document.getElementById('id名字');
因为id是唯一的,所以拿到的是一个元素 - document.getElementsByTagName('标签名');
标签名拿到的是一个元素集合;即使只有一个元素,也是个集合
想要取到其中的一个:aDiv[0] aDiv[2]
- document.getElementById('id名字');
-
JS中的数据类型
- 基本数据类型:
- 字符串string
- 数字 number
- 布尔值 boolean
- undefined 现在没有,以后也没有
- null 空对象,现在没有,以后会有
- 引用数据类型
- 对象数据类型
- 数组
- 正则
- 对象{}
- 函数数据类型
function 函数名(){};
- 对象数据类型
- 基本数据类型:
-
数据类型检测的方式
- typeof 可以检测基本数据类型(所有经过typeof的都是字符串),但是对于对象数据类型,检测出来的都是object,无法知道具体属于哪种对象
- 对象 instanceof 类; 比如
ary instanceof Array
判断这个实例是否属于某个类 - 对象.constructor: 比如
ary.constructor
可以打印出对象所属的类 - Object.prototype.toString.call(ary); 出来的结果 '[object Array]'
-
基本数据类型和引用数据类型的区别:
- 基本数据类型:是对值的操作
- 引用数据类型:是对地址的操作
-
操作属性用的是"." oDiv.style.display='block'
-
其他数据类型转为number数据类型
- 强制转换
- Number()
- parseInt()
- parseFloat()
- 一个严格转换
- Number()
- 两个非严格转化
- parseInt() 只能转化为整数
- parseFloat() 可以保留小数
如果转换失败的话,返回的结果是NaN:not a number 不是数字;但是NaN是number数据类型
- 强制转换
-
关于NaN:
- NaN是number数据类型
- isNaN() 判断是否为非有效数字; 非有效数字:true; 有效数字:false
-
循环由4部分组成:
- 1)定义 2)条件 3)语句 4)自增
-
常见的循环方式:
- for() :类数组arguments,htmlCollection,数组[],字符串
- for in():普通对象{}
- while(){}和for循环的区别和联系
- 用while()循环也可以实现for循环的四步
- for循环一般用在循环次数固定; while()循环次数不固定
- do...while() 不管条件是否成立,都会先执行一次
-
函数由两部分组成:
- 函数定义3阶段
- 开辟一个内存空间
- 把函数体内所有的JS代码,作为字符串存在这个空间中
- 把空间地址赋值给函数名
- 函数调用2阶段
- 当函数被调用的时候,会形成一个私有作用域
- 把内存中的字符串作为JS代码来执行
只定义不调用,函数不会执行
- 函数定义3阶段
-
闭包
- 定义:
- 当函数被调用的时候会形成一个私有作用域,保护里面的变量不受外界的干扰,函数的这种保护机制叫做闭包
- 闭包就是在提供了一个在外部访问另一个函数内部局部变量的方式
- 定义:
var add = (function(){
var count = 0;//外部访问的计数器,局部变量.
var fun = function(){
return ++count;
}
return fun;
})();
//还可以这样写
var add2 = (function(){
var count = 0;//外部访问的计数器,局部变量.
function plus(){
return ++count;
}
return plus;
})();
//还可以这样写
var add3 = (function(){
var count = 0;//外部访问的计数器,局部变量.
return function(){
return ++count;
}
})();
- 作用:
- 避免全局变量名冲突
- 在闭包中通过“window.xx”去修改全局变量;如果闭包中没有定义此变量,也可以直接修改变量去影响全局
- 封装(闭包中封装的方法在全局不能使用,只能通过“window.xx=封装的函数名”把方法导出)
- 保存正确的i值
- 特性:
- 函数嵌套函数
- 函数内部可以引用外部的参数和变量
- 参数和变量不会被收回
- 函数自带的参数机制叫做arguments;
- arguments:能拿到实参,并且以类数组的形式展现; 类数组也是对象,是对象都有属性和方法
- arguments.callee 拿到的是当前函数本身
- arguments.length 拿到实参的长度/个数
- 数字常用的方法:
- toFixed(要保存的位数)四舍五入的保存小数位数的
- 属性和方法的区别:
- 属性没括号,方法有括号;方法本质就是对函数的调用
- 对象的属性不会报错,如果没有,undefined; 方法不存在的话,会报错
- 属性操作:. 和 []
- 如果遇到变量,属性名[变量名] 注:千万不要给变量加引号
- 如果遇到属性名为数字,属性名[1]
- 参数有两种
- 形参
- 形参是私有变量
- 如果定义了形参,但没有赋值,拿到是undefined
- 形参个数不确定的话,用arguments来获取参数
- 函数自带的参数机制arguments
- arguments可以打印出实参,以类数组的形式打印出来
- 0,1,2可以找到对应的属性值
- arguments.callee;代表当前函数本身
- arguments.length;打印出实参的个数
- 形参
- 函数返回值:
- 函数返回值通过return;来返回
- 获取值的时候,需要返回值;设置值的时候,不需要返回值
- undefined出现的几种情况:
- 属性:当对象的属性名不存在的话,拿到的是undefined
- 参数:如果定义了形参,但是没有传实参,拿到的是undefined
- 没有设置函数返回值,即没有写return,拿到的函数返回值为undefined
- 写了return但没有赋值,拿到的函数返回值也是undefined
- NaN出现的几种情况:
- 转化失败时
- 无效运算时:null+undefined、undefined+undefined
- 运算符:
- 算术运算符:+ - * / %
- %(取余):技巧-有几种情况就%几
- 比较运算符:
> , >= , < , <= , == ,!= ,=, ! - 逻辑运算符:
! && ||- &&:两边都成立才能成立;但是也可以用它做条件判断; 9%3==0 && alert('能整除')
- ||:一般成立就算成立;也可以用它做条件判断;9%3!=0 || alert('能整除')
- 赋值运算符
=; += ; -= ; *= ; /= ; %= - 运算符的优先级:算术》比较》逻辑》赋值
- 算术运算符:+ - * / %
- 条件判断:
- if(条件1){....}else if(条件2){...}else
- 条件?语句1:语句2;
- switch:用于多条件判断
每一种case情况其实都是相当于在用“===”进行比较switch(判断的是可变的值){ case a: 语句1; break; case b: 语句2; break; default: 语句3; break; }
- 如果只有一种条件,有三种写法:
- if(条件)
- 条件?语句1:null;
- if(条件) 语句1;
- 9%3==0 && alert('能整除');
- 9%3!=0 || alert('能整除');
数组常用的方法
第一组:增加,删除和替换
- push()
- 作用:给数组末尾增加一项
- 需要实参
- 返回值:新数组的长度
- 原数组发生改变
- pop()
- 作用:删除数组最后一项
- 不需要参数
- 返回值:被删除的内容
- 原数组发生改变
- unshift()
- 作用:给数组开头增加一项
- 需要实参
- 返回值:新数组的长度
- 原数组发生改变
- shift()
- 作用:删除数组第一项
- 不需要参数
- 返回值:被删除的内容
- 原数组发生改变
- splice()
- 插入/增加 splice(index,0,要添加的内容)
- 作用:在指定的索引前面,插入我们要添加的内容
- 参数:3个
- 返回值:[]空数组,里面没有内容
- 原数组发生改变
- 删除 splice(index,m)
- 作用:从指定的索引地方开始,删除m个;如果第二个参数不写,就从索引一直删除到结尾
- 参数:2个
- 返回值:被删除的内容,以一个新数组的形式返回
- 原数组发生改变
- 替换 splice(index,m,n)
- 作用:从指定的索引开始,删除m个,并替换为n的新内容
- 参数:3个
- 返回值:被删除的内容,以一个新数组的形式返回
- 原数组发生改变
- 插入/增加 splice(index,0,要添加的内容)
第二组:克隆和截取/查找
- slice(n,m)
- 作用:从索引n开始,查找到索引m,包前不包后
- 参数2个
- 返回值:查找的内容
- 原数组没有发生改变
- 克隆的功能:slice(0)/slice()
面试题:请找到数组中[n,m]项(答案:ary.slice(n-1,m))
- concat()
- 作用:数组拼接 / 克隆ary.concat()
- 参数:不确定,想拼接几个数组,里面参数就写几个数组名,也可以写成数组的形式
- 返回值:拼接成的新数组
- 原数组没有发生改变
第三组:数组转字符串
- toString()
- 作用:数组转字符串
- 参数:无
- 返回值:以逗号分割的新字符串
- 原数组没有发生改变
- join(拼接形式) 拼接形式可以为任何运算符号
- 作用:数组转字符串
- 参数:拼接形式可以为任何运算符号
- 返回值:以指定的拼接形式分割的新字符串
- 原数组没有发生改变
- 如果拼接形式为+之类的,想实现运算,可以用eval()
- eval():把字符串作为JS代码来执行
第四组:数组的翻转和排序
- 数组翻转 ary.reverse()
- 功能:数组翻转
- 参数:没有
- 返回值:被翻转后的数组
- 原数组发生改变
- 数组排序
ary.sort(function(a,b){
return a-b;//从小到大排; return b-a 从大到小排
})
第五组:数组常用但不兼容的方法
- indexOf()
- 功能:查找内容
- 参数:要查找的内容
- 返回值:如果找到,返回内容对应的索引/位置; 如果没找到,返回-1
- 原数组不变
- forEach():遍历数组的
- 作用:遍历数组的
- 参数有两个:1)callback 2)context:改变this指向的
- callback中有三个参数:item,index,input
- 返回值:undefined; 没有返回值
- 原数组不变
- map():也是遍历数组,跟forEach()功能一样,只是forEach()没有返回值;map有返回值
Math常用的方法
- Math.round() 四舍五入
- Math.floor() 向下取整
- Math.ceil() 向上取整
- Math.abs() 绝对值
- Math.sqrt() 开平发
- Math.pow() 幂次方
- Math.max() 最大值
- Math.min() 最小值
求n-m之间的随机整数:Math.round(Math.random()(m-n)+n);
字符串常用的方法:
- 通过下标找对应的字符
- charAt() 返回指定位置的字符
- charCodeAt() 返回在指定的位置的字符的 Unicode 编码
- 通过字符找下标
- 从前往后找:indexOf()
- 从后往前找:lastIndexOf()
- 字符串截取
- slice(n,m) 从索引n截取到索引m;不包含m;包前不包后;但是,slice可以取负值
- substr(n,m) 从索引n开始,截取m个
- substring(n,m) 从索引n截取到索引m;不包含m
- 字符串转数组
- split(切割形式:字符串或正则表达式) 把字符串分割为字符串数组,返回一个字符串数组
- 转大小写
- toUpperCase() 把字符串转换为大写
- toLowerCase() 把字符串转换为小写
- 跟正则配合的字符串方法
- split() 把一个字符串分割成字符串数组
- match() 检查一个字符串是否匹配一个正则表达式
- replace('a','b') 把a替换为b;替换与正则表达式匹配的子串
- search() 检索与正则表达式相匹配的值;找到的情况下,返回对应内容的索引;找不到的返回-1
- 其他数据类型转为number数据类型
- 一个严格转换Number(),两个非严格转换parseInt() parseFloat()
- 转换失败是NaN
- [] 默认通过 toString() 转成空字符串; Number("")===0
- null默认转为0;null+10=10; undefined+10=NaN
- false=0; true=1
- 其他数据类型转为布尔数据类型
- Boolean()
- 假:"",0,NaN,null,undefined,false
- 真:除了假都是真
- if(一个值) 会转成布尔
- if(表达式/比较) 会默认转成布尔
- !
- Boolean()
- 其他数据类型转成字符串数据类型
- 对象转字符串:toString()
- 数字转字符串:""+数字
- 数据类型的比较:
- 对象对象 比较的是地址 [][] false
- 字符串对象 转成字符串 ""[] true
- 字符串数字 转成数字 ""0 true
- 字符串布尔值 转成数字 ""![] true
- 数字对象 转成数字 0[]
- 布尔值对象 转成数字 false[] ![]==[]
- 数字布尔值 转成数字 false![]
- null==undefined true
- null===undefined false
- NaN==NaN false ;NaN跟任何值都不相等,包括自己也不相等
- 给数组末尾增加一项
- push()
- ary[ary.length]=xxx;
- ary.splice(ary.length,0,xxxx);
- 删除数组最后一项
- pop()
- ary.length--; ary.length-=1; ary.length=ary.length-1;
- ary.splice(ary.length-1,1);
- 如何实现克隆
- ary.slice();/ary.slice(0)
- ary.concat();
- ary.splice(0) 注意:如果用splice()进行克隆,0不能省略
- for循环也可以实现;但for循环是循环,不是方法
- 定时器
- 隔一段时间爆发一次:
- setInterval(callback,毫秒数);
- 关闭定时器 clearInterval(定时器的名字)
- 只爆发一次:
- setTimeout(callback,毫秒数);
- 关闭定时器 clearTimeout(定时器的名字)
- 隔一段时间爆发一次:
- n++ 和 ++n的区别
- ++n 先++,再运算;累加后的结果参与了运算
- n++ 先运算,再++; 累加后的结果不参与运算
- 创建数组的两种方式
- var ary=[1,2,3]; 字面量方式创建
- var ary2=new Array(1,2,3); 实例创建
- DOM树:由一大堆的元素和标签组成;所以DOM就是用来操作页面中的标签的
- DOM中的获取方式有以下几种:
- id
- className
- tagName
- name
- 可视区的宽度:document.documentElement.clientWidth||document.body.clientWidth;
- 可视区的高度:document.documentElement.clientHeight||document.body.clientHeight;
- querySelector() #id .class div 拿到的是一个元素
- querySelectorAll() #id .class div 拿到的是一组元素
- 节点:
节点类型 | 说明 | 值 |
---|---|---|
元素节点 | 每一个HTML标签都是一个元素节点(例如: 、等) |
1 |
属性节点 | 元素节点(HTML标签)的属性(例如:id 、class 、name 等) | 2 |
文本节点 | 元素节点或属性节点中的文本内容 | 3 |
注释节点 | 表示文档注释,形式为 | 8 |
文档节点 | 表示整个文档(DOM 树的根节点,即 document ) | 9 |
-
DOM动态操作
- 创建新标签
- document.createElement(标签名) 创建
- 克隆 obj.cloneNode(false/true);//false:只克隆表面; true:深度克隆
- 动态插入
- 父级.appendChild(新元素) 插入到父容器的末尾
- 父级.insertBefore(newEle,oldEle) 插入到指定元素的前面
- 删除标签
- 父级.removeChild(获取到的元素名)
- 创建新标签
-
属性操作
- . 和 []
- attribute
- setAttribute(属性名,属性值) 设置属性
- getAttribute(属性名) 获取属性
- removeAttribute(属性名) 移除属性
- 1)通过点来设置自定义属性,看不到;但是通过setAttribute()可以看到;
2)通过点获取元素身上已经定义好的的自定义属性,获取不到;但是通过getAttribute()可以拿到;
注意:用"."都用点,用attribute,都用attribute;千万不要混搭!
-
判断属性是否存在的方法
- in: "属性名" in 对象 如果支持,返回true;不支持返回false
- ".": 对象.属性名 如果不支持,返回undefined
-
预解释:当前作用域下,在JS代码执行之前浏览器会对带var和带function的进行提前声明或定义
-
带var和带function的声明和定义不同:
- 带var的,只声明不定义
- 带function,声明+定义
-
函数定义三步骤:
- 开辟一个空间地址
- 把函数体内所有JS代码作为字符串放在这个空间中
- 把空间地址赋值给函数名=
-
函数调用四步骤:
- 形成一个私有作用域
- 形参赋值
- 预解释
- 代码从上到下的执行
-
上级作用域
上级作用域跟函数在哪里调用无关,只跟函数对应的堆内存在哪里开辟有关 -
作用域链
- 当函数被调用的时候,会形成一个私有作用域;在这个作用域中查找是否有私有变量a
- 如果有私有变量a:那么整个函数体内的所有a都是私有变量,跟外界没有任何关系
- 如果没有私有变量a:去上级作用域找,找不到,继续往上级找,如果找到window还没有的话,报错!
-
私有变量主要有两种
- 函数体内带var的
- 形参
- 内存包含:堆内存和栈内存
- 堆内存:用来存放数据
- 对象数据类型的
- 存的是键值对 key=value
- 函数数据类型的
- 代码字符串
- 对象数据类型的
- 堆内存的释放:
var a=[1,2,3,4]
释放:a=null - 栈内存:本身提供了一个供JS代码执行的环境
- 包含:全局作用域 和 私有作用域
- 全局作用域的形成和销毁:
- 形成:当一个页面被浏览器加载完成的时候,全局作用域就形成了
- 销毁:1)关闭页面 2)关闭浏览器
- 私有作用域的形成和销毁:
- 形成:当函数被调用的时候,会形成私有作用域
- 销毁:一般情况下,当函数执行完成的时候,默认就被销毁了;但是两种情况下不销毁:
- 不销毁:当函数体内的东西被外面的变量或者其他占用的话,就不销毁
- 不立即销毁:当函数执行完成的时候,会返回一个函数,被返回的函数还需要再执行一次;只有所有的调用都完成的时候,这个函数才能销毁
- 预解释无节操
- 只对等号左边带var的,声明但不定义
- 自执行函数不会进行预解释,只有,执行到他的时候,声明+定义+调用同步完成
- 已经声明过的不会进行重复声明,但会重新赋值
- return下面的语句虽然不会执行,但会进行预解释
- 函数的声明早于变量的声明
- (在IE10及10以下浏览器下)在条件判断语句中,无论条件是否成立,都会进行预解释
不要在条件判断语句中写函数的定义阶段;否则,各大浏览器对其的兼容性不同
全局变量,都是window的全局属性;
全局函数,都是window的全局方法。
比如:
setInterval()
setTimeout()
alert()
confirm()
- 关于this
- 当一个元素身上的事件被触发的时候,会执行一个函数,函数中的this指向当前这个元素
- 自执行函数中的this,永远都是window
- 回调函数中的this,一般都是window
setInterval(函数名,1000) ; ary.sort(function(){}) ; - 当函数被调用的时候,看前面是否有".","."前面是谁,this就是谁
- 当遇到call、apply、bind时,以上规律失效;因为他们可以改变this指向
- 箭头函数中的this指向父函数中的this
- 改变this指向的函数:
- call(arg1,arg2,arg3,arg4......)
- call的一个参数用来改变call前面的函数中的this关键字
- call从第二个参数开始,相当于给call前面的函数从左往右一个个的赋值;
- call当改完this指向,传完参数后,立即执行了
- apply(arg1,arg2) arg2可传可不传
- arg1用来改变this指向,具体跟call一样
- 区别:apply的第二个参数是个数组,存放所有需要给形参的值;
虽然apply的第二个参数是个数组,但是对于形参来说,也是从左往右一个个的赋值
- bind(预处理机制)
- bind的传参形式跟call一样
- 注:bind属于预处理机制,当调用bind的时候,会返回一个已经改好this,传好参数的函数,你只需要在需要的时候,调用即可
- call(arg1,arg2,arg3,arg4......)
- 带var和不带var的区别:
- 带var:
1)会进行预解释
2)如果在全局作用域下,他就是window的全局属性 - 不带var:
1)不会进行预解释
2)不带var在"赋值"的时候,相当于window添加全局属性
- 带var:
面向对象
-
对象两大特征:属性 和 方法
-
面向对象(oop,oo)思想的特点:
- 封装:对于同一个功能,只需要封装一次,以后再使用的时候,只需要调用即可,无需重写;低耦合高内聚
- 继承:子类可以继承父类的属性和方法
- 多态:重载 和 重写
- 重载:JS上没有严格意义上的重载;但有类似重载的功能,就是传不同的参数,有不同的返回值
- 重写:子类可以重写父类的属性和方法
-
面向对象的四种常见设计模式:
- 单例模式
- 把同一个对象上的属性和方法,都放在同一个命名空间
- 单例模式的本质:普通对象
- 模块化开发:对于一个复杂的大项目,可以分配给不同的工程师同步进行开发;等项目完成的时候,合并即可
- 各个模块之间的相互调用:对象名.属性名
- 本模块之间的相互调用:this.属性名
** 缺点:造成大量冗余代码**
- 工厂模式
- 工厂模式有3步:
- 引进原材料 创建一个空对象{}
- 加工原材料 加工对象:给对象添加属性和方法
- 输出产品成 输出对象: return
- 工厂模式,为了让他长的像系统的类 new Array()
- 工厂模式和构造函数模式的区别:
- 在调用的时候:
工厂模式 person()
构造函数模式 new Person() - 在函数体内
工厂模式三步:1)创建对象 2)给对象添加属性和方法 3)返回对象
构造函数模式只有一步:2)给对象添加属性和方法 ; 第一步和第三步系统帮做了,系统提供了一个对象叫this
- 在调用的时候:
- 工厂模式有3步:
- 构造函数模式
1.构造函数首字母一定大写
2.构造函数中放的都是私有的属性和方法
3.原型上放的都是公有的属性和方法
4.系统默认会创建一个对象,this
5.系统默认会返回一个对象 this
6.构造函数中的this,指向当前这个实例(构造函数new给谁,this就指向谁) - 原型模式
- 原型模式基础:
- 每个函数数据类型(普通函数,类),都有一个属性,叫做prototye,prototype是个对象
- prototype这个对象上,天生自带一个属性,叫做constructor,指向当前所属类
- 每个对象(普通对象,实例,prototype)身上,都有一个属性,叫做
__proto__
,指向当前对象所属类的原型
- 原型链:
__proto__
如果要查找 对象.属性名 比如f1.showX- 先在自己的私有作用域中查找;如果找到,那么这个属性是私有属性
- 如果没找到,到当前实例所属类的原型上找(f1.
__proto__
),如果找到属于公有的属性或方法 - 如果没找到,继续通过
__proto__
往上找,一直找到Object.prototype上还没有的话,undefined
- 要形成的几个条件反射:
- 一看到构造函数:存的都是私有的属性和方法
- 一看到prototype:存的都是公有的属性和方法
__proto__
原型链
- 原型模式基础:
- 单例模式
-
两大boss:Object 和Function
1 Function 是 Object 的爹
2 Object 是 Function 的爹
3 Object 是 Function.prototype的爹
4 Object.prototype 是 Function.prototype的爹 -
函数的三种角色:
- 普通函数:形成一个私有作用域,形参赋值,预解释,代码执行,内存和内存释放,作用域链
- 类:实例,prototype,constructor,类,原型链
__proto__
- 普通对象:具有普通对象的特征:属性和方法
-
如果给原型自定义了一个对象,那么自定义的这个对象上,没有constructor
-
属性判断
- in:判断某个属性是否在元素上(包含了私有+公有)
- hasOwnProperty判断某个属性是否为元素身上的私有属性
使用 obj.hasOwnProperty(属性名) - 写一个方法:判断是否为公有属性
- isPrototypeOf:判断前一个对象是否在后一个对象的原型链上;返回的布尔值
- propertyIsEnumerable:他的作用跟hasOwnProperty类似;返回的布尔值
-
继承:子类继承父类的属性和方法
- call继承:子类只继承父类私有的属性和方法;父类私有的属性和方法,都在父类的构造函数里
- 拷贝继承:私有通过call来继承,公有通过extend() 来继承
- 原型继承:
- 私有继承:call继承
- 公有继承:父类原型上的属性和方法,只有父类中的实例可以使用
- 子类原型可以使用父类原型上的属性和方法;子类原型作为父类的实例
- 类数组转数组
- 类数组有两种:
- arguments
- htmlCollection 元素集合
- 浏览器异常捕获
try....catch(e){}...finally{..}
平常用的,只有 try...catch...
使用场景:只要有报错的情况,建议用try...catch.... - JSON: JOSN 是系统window的属性
- JSON.parse() 把JSON格式的字符串,转成JSON格式的对象
- JSON.stringify() 把JSON格式的对象,转成JSON格式的字符串
注意JSON,属性名一定是双引号"";属性值,如果是数字,可以没有引号
- eval() 容易引起"注入攻击"
- 类数组有两种:
- sort排序
- DOM映射:html页面中的DOM结构,跟通过JS获取到的元素集合htmlCollection之间,存在一一对应的关系
- appendChild() 有类似剪切的功能
- sort排序三步骤:
1 类数组转数组
2 sort排序
3 把排好序的内容,重新插入页面 - 把数据插入页面的几种方式
- 字符串拼接; _插入页面用innerHTML
- 动态创建和插入; document.createElement() 父级.appendChild(元素)
- 文档碎片:
1)先把创建好的每个元素,放入文档碎片
2)最后把文档碎片放入父元素中
3)释放文档碎片
- DOM映射:html页面中的DOM结构,跟通过JS获取到的元素集合htmlCollection之间,存在一一对应的关系
- 前端往后台的请求方式:
- GET 请求数据
- POST 发送数据
- DELETE 删除数据
- PUT 提交数据
- 同步和异步:
- 同步:每次只能完成一个任务,必须等这个任务完成之后,才能开始下个任务
- 异步:当前的任务没完成,不用等待,继续开始下个任务,也就是,可以多个任务并行
- 回调异步
- 事件
- 定时器
- ajax
- http响应状态码
- 2xx 成功
- 3xx 重定向
- 4xx 请求错误
- 400 请求的参数错误
- 404 文件没找到
- 5XX 服务器错误
-
正则(手册:http://tool.oschina.net/uploads/apidocs/jquery/regexp.html)
- 作用:玩字符串的
- 定义:通过制定一系列的规则来操作(校验/匹配、捕获)字符串
- 校验: reg.test() ;/^2\d{2}/.test(xml.status);
- 捕获:1)str.match(reg) 2)reg.exec(str); 3)str.replace(reg);
正则的方法: reg.test() reg.exec()
字符串的方法:str.match() str.replace() str.split() str.search();
-
创建正则的方式:
- var reg=/^2\d{2}/; 字面量的创建方式
- var reg=new RegExp(); 实例创建
-
字面量创建和实例创建的区别:
- 字面量创建无法拼接变量,实例创建可以拼接变量
- 字面量创建不需要转义,实例创建需要转义
-
正则由元字符和修饰符两部分构成: var reg=/^2\d{2}/g;
- 元字符:就是包含在两个斜杠之间,陌生的字符
- 修饰符:就是斜杠外面的
-
元子符包含:特殊含义的元字符和量词元字符
- 特殊含义的元字符:
\ 转义
| 或
() 分组
. 除了\n以外的其他字符
\n 换行
\b 开头结尾和空格
^ 开头
$ 结尾
\s 空格 \d 数字 \w 数字,字母,下划线
\S 非空格 \D 非数字 \W 非数字,非字母,非下划线
[a-z] 任意一个小写字母
[^a-z] 除了字母以外的任何一个字符
[abc] “a,b,c”中的任意一个字母
[^abc] 除了“a,b,c”以外的任意一个字母 - 量词元字符
*
重复0次或多次+
重复1次或多次?
0 或1,可有可无- {n} 正好n次
- {n,} 最少n次;n次到多次
- {n,m} n次到m次
- 特殊含义的元字符:
-
修饰符:
- g 全局
- m 换行
- i 忽略大小写;ignore
-
()小括号的用法:
- 提高优先级 /^(18|19)$/
- 分组的作用
-
[]中括号的用法:
- 中括号中不会出现两位数
- 像类似于.-之类的,在中括号中都没有特殊函数
-
?问号的作用:
- 可有可无
- 解决正则捕获的贪婪性
-
捕获
- 正则中的捕获,主要讲三点:
- exec: reg.exec(str);
- match: str.exec(reg);
- replace:str.replace(reg,xxxxxx)
- 正则捕获有两大特点:
- 懒惰性:
- 解决措施:添加全局g
- 加了全局g,会影响lastIndex(从你找到内容 的 下一项内容的 索引 开始查找)
- 贪婪性:
- 解决措施:在量词元字符后面加上?
- 懒惰性:
- exec,是正则的方法,每次只能拿到一个值;返回的结果是个数组,默认情况下,数组有3项:
- 符合大正则的内容
- index:找到的内容所对应的索引;(位置)
- input:原始字符串;
如果有小分组的情况下,小分组从数组的第二项开始;数组的长度也会因为小分组而增加
- match:是字符串的方法,每次能到所有符合正则的内容,并且以一个新数组的形式返回
- exec和match的区别:
- exec每次只能拿到一个值;match能拿到所有值,并以新数组的形式返回
- exec能拿到小分组; match只能拿到大正则,无法拿到小分组
- 正则中的捕获,主要讲三点:
-
replace
- replace中的回调函数,默认接收三个参数,如果有小分组,arguments的长度会扩充
- replace回调函数中第一个参数的运用:敏感词过滤
- replace回调函数中第2个参数的运用:把数字作为数组的索引,找到对应的值
-
统计出现次数最多的单词
思路1:
1) 利用对象不重名的特性
2) 假设法
3) 字符串拼接
思路2:
1)字符串排序:字符串转数组-数组排序-数组转字符串
2)假设法+重复子项 /(\w)\1+/gi; -
解析URL地址: /([&?=]+)=([&?=]+)/g;
-
日期格式化:
重点,字符串转成数组,三种思路:
1)严格匹配;
var reg=/^(\d{4})[/-](\d{2})[/-](\d{2}) (\d{2}):(\d{2}):(\d{2})$/;
var ary=null;
str.replace(reg,function(){
ary=Array.prototype.slice.call(arguments,1,arguments.length-2)
});
- split 切
var ary=str.split(/[^\d]+/g); - match 捕获
var ary=str.match(/\d+/g);
- ?的用法
1) 0或1
2) 解决正则捕获的贪婪性 +?
3) 只匹配不捕获 (?:\d+) - 小括号的用法:
1)分组
2)提高优先级
3)只匹配不捕获 (?:\d+) - var reg=new RegExp();
- 在有全局g的情况下,能影响lastIndex的值的属性有两个:
1)reg.test()
2) reg.exec() - 回调函数需要注意的几点:
- 回调函数被调用的次数;比如,map中回调函数被调用的次数,取决于数组的长度
- 回调函数是否需要传参;比如,map中回调函数接收三个参数
- item
- index
- input
- 回调函数中this默认指向window,可以通过call来改变this指向
- 回调函数是否有返回值;比如 forEach()没有返回值; map()有返回值,他是把每个回调函数的返回值保存在一个数组中,最后返回出map
- CSS盒子模型
- 构成:手动设置的宽高+padding+border+margin
- JS盒子模型
- 主要通过元素身上提供的属性和方法,来获取元素身上的样式值
- JS中盒子模型所设计的属性和方法,主要包含以下几类:
- client系列:clientWidth clientHeight clientLeft clientTop
- clientWidth/clientHeight: 手动设定的宽度/高度+左右/上下padding
- clientLeft/clientTop: 左边框的宽度 / 上边框的宽度
- offset系列:offsetWidth offsetHeight offsetLeft offsetTop offsetParent
- offsetWidth/offsetHeight:手动设定的宽度/高度+左右/上下padding+左右/上下的border宽度
(clientWidth+左右border clientHeight+上下border) - offsetLeft/offsetTop:当前元素的外边框距离他定位父级的内边框之间的距离
- offsetParent: 定位上的父级
- scroll系列:scrollWidth scrollHeight scrollLeft scrollTop
- scrollWidth/scrollHeight:
- 在内容没有溢出的情况下,
scrollWidth/scrollHeight等于clientWidth/clientHeight; - 如果内容溢出的情况下,
scrollHeight约等于上padding+真实内容的高度
为什么是约等于:
1)当内容溢出的情况下,不同浏览器拿到的值不同
2)同一浏览器下,内容是否溢出拿到的值也不同
- 在内容没有溢出的情况下,
- scrollTop:指当前页面被浏览器卷去高度
- JS盒子模型遇到的问题
- JS盒子模型中求出来的都是四舍五入的整数,无法拿到小数 --不解决
- JS盒子模型中拿到的值都是复合值,无法拿到单独的宽或高; --解决:封装getCss
- 关于盒子模型的偏移量,我们只能求出当前容器的外边框到定位父级的那边框之间的距离,无法求出当前定位元素到body的距离;--解决:封装offset
- 求可视区的宽高或被浏览器卷去的高度和宽度,太麻烦了;-- 封装win
- 箭头函数
- 表达式
- var fn=p=>p;
- var fn=()=>'我没有参数';
- var fn=(n,m)=>n+m;
- 函数体
- var fn=p=>{return p};
- var fn=()=>{return '我没有参数'};
- var fn=(n,m)=>{return n+m}
注:箭头函数中的this,指向父函数的this
- 表达式
- 类的创建和继承
- 类的创建
class 类名{
constructor(){//写私有的属性和方法
}
getName(){//公有的属性和方法
}
static getAge(){//类的静态方法;也是类的私有方法,实例不能使用
}
}
类.xxxx=xxxx;//类的私有属性
- 类的继承
class S extends F{
constructor(name,age,color){
super(name,age);
this.color=color;
}
//下面正常写子类公有的
}
- 解构赋值:{属性名}=persion;//实际拿到的是对象身上该属性名对应的值
- let 和 const
- 他两都不能进行预解释
- let会形成块级作用域
- const 是个常量,不能进行更改
- $(document).ready() 和 window.onload的区别:
- window.onload 是等页面所有的内容(图片,音频,视频,DOM结构.....)都加载完成的时候,才执行JS代码
- $(document).ready(function(){...代码}) 只要DOM结构加载完成,就开始执行JS 代码
- jQuery选择器
- 基本选择器:
$('#div') $('.div') $('div') $('.div1,.div2');
- 基本选择器:
- JS和jquery只能共存,不能混淆
- JS 转成jquery:只需要被$包裹即可; $(this) $(oDiv)
- jquery转JS: [index] get(index)
- jquery中DOM常用方法
- append 和 appendTo
联系:功能相同,但是针对的主体不同 - 创建元素 $('') $('')
- append 和 appendTo
-
运动
- show() 显示隐藏的元素
hide() 隐藏显示的元素 - slideDown() 通过使用滑动效果,显示隐藏的被选元素
slideUp() 通过使用滑动效果,隐藏被选元素,如果元素已显示出来的话 - fadeIn() 使用淡入效果来显示一个隐藏的元素
fadeOut() 使用淡出效果来隐藏一个元素 - animate(target,time,effect,callback) 执行 CSS 属性集的自定义动画
stop() 停止当前正在运行的动画
- show() 显示隐藏的元素
-
ajax前后端数据交互
ajax({
type:'get/post',
url:'xxxx?'+Math.random()*1000000+new Date().getTime(),
async:true/false,
dataType:'json',//解决了jsonParse()
data:$('form').serialize()//表单序列化:就是把前端要传后台的数据,以k=v&k=v拼成字符串
success:function(){//成功之后的回调
},
error:function(){//失败之后的回调
}
})
- 事件和事件绑定
- 事件绑定:2个
on(type,fn) //可以执行多次
one(type,fn) //只能执行一次 - 解除绑定
off(type,fn);//注意:只能解除有名字的函数
- 事件绑定:2个
- each和map
- $().each() 和 $.each()的区别:
- $().each() 只能遍历jquery获取到的元素
- $.each() 既可以遍历jquery元素也可以遍历原生数组和原生对象
- $().map() 和 $.map() 他们 与 each的区别
- map的回调函数接收的参数,跟each的顺序正好相反
- map可以返回一个新的数组;而each拿到的还是原来的数组
- $().each() 和 $.each()的区别:
- 事件
- 鼠标事件:
onclick ondbclick onmouseover onmouseout onmouseenter onmouseleave - 系统事件:
onload resize onscroll - 键盘事件:
onkeydown onkeyup onkeypress - 表单事件:
onfocus onblur autofocus=true/false;
- 鼠标事件:
- 事件分类:DOM0级事件 和 DOM2级事件
- DOM0级事件 和 DOM2级事件的区别:
- DOM0级事件:
1)在元素的私有属性上
2)同一个元素,同一个行为,只能绑定同一个方法;如果多次绑定,后面的方法会覆盖前面的方法
3)只能发生在事件流的冒泡阶段 - DOM2级事件:
1)在元素所属的EventTarget这个类的原型上
2)同一个元素,同一个行为,可以绑定多个不同的方法
3)可以人为的控制发生事件流的哪个阶段(捕获,冒泡)
- DOM0级事件:
- DOM0级事件 和 DOM2级事件的区别:
-
标准浏览器下:
addEventListener(type,fn,useCapture);- 解绑:
removeEventListener(type,fn,useCapture);
注意:所有的行为,都不加on
- 解绑:
-
IE6-8下:
attachEvent('on'+type,fn)- 解绑:
detachEvent('on'+type,fn);
attachEvent只能发生在冒泡阶段
- 解绑:
- 事件流
- 由三部分构成:捕获,target事件源,冒泡
- 由两部分构成:捕获,冒泡
注意顺序:先捕获,后冒泡
- 一个元素的层级嵌套:
元素自己->HTMLDivElement ->HTMLElement->Element->Node->EventTarget->Object - 事件对象
- 事件对象的兼容处理:e=e||window.event
- 事件源:e.target=e.target||e.srcElement;
- 坐标:距离当前可视区左上角的坐标-兼容:e.clientX; e.clientY;
- 坐标:距离第一屏左上角的坐标:e.pageX;e.pageY;
不兼容:
e.pageY=(document.documentElement.scrollTop||document.body.scrollTop)+ e.clientY;
e.pageX=(document.documentElement.scrollLeft||document.body.scrollLeft)+ e.clientX; - 事件类型:e.type
- 键码:e.keyCode
- 阻止默认事件: e.preventDefault?e.preventDefault():e.returnValue=false;
- 阻止冒泡 e.stopPropagation? e.stopPropagation():e.cancelBubble=true;
- 熟悉标准浏览器中的DOM2级事件绑定
- addEventListener特点:(标准浏览器)
- 按"绑定的"先后循序执行的
- this指向当前被绑定事件的这个"元素"
- 如果给同一个元素,同一个行为绑定多次同一个方法,实际上只执行一次
- attachEvent的问题:
- 顺序不对
- this不对,attachEvent中的this,默认指向window
- 如果给同一个元素,同一个行为绑定多次同一个方法,执行的是多次;也不对
- addEventListener特点:(标准浏览器)
补充
-
null和undefined区别:
- 定义变量时:null现在没有,以后会有;undefined:现在没有,以后也没有
- null转为数值为0,undefined转为数值为NaN
- 报错时:undefined表示“缺少值”,即 此处应该有一个值,但没定义;null表示“没有对象”,即 此处不该有值
-
性能优化
- 网页内容
- 减少 http请求次数
- 减少 DNS查询次数
- 避免页面跳转
- 缓存 Ajax
- 延迟加载
- 提前加载
- 减少 DOM元素数量
- 避免 404
- 服务器
- 使用CDN(内容分发网络)
- 添加Expires或Cache-Control报文头
- Gzip压缩传输文件
- CSS
- 将样式表置顶
- 用代替@import
- JavaScript
- 把脚本置于页面底部
- 使用外部JavaScript和CSS
- 精简JavaScript和CSS
- 去除重复脚本
- 减少DOM访问
- 图片
- 优化图像
- 优化CSS Spirite
- 不要在HTML中缩放图片
- favicon.ico要小而且可缓存
- 网页内容
-
如何解决跨域问题
jsonp 原理:动态插入script标签 -
JavaScript同源策略
这里的同源策略指的是:协议,域名,端口相同。同源策略是一种安全协议,指一段脚本只能读取来自同一来源的窗口和文档的属性。 -
哪些操作会造成内存泄漏?
1、内存泄漏指任何对象在您不再拥有或需要它之后仍然存在
2、垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),那么该对象的内存即可回收
3、setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环) -
事件代理(Event Delegation) 即 事件委托
-
定义:把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务
-
原理:DOM元素的事件冒泡
-
优点:提高性能