JAVAScript总结
JavaScript基础
es6 = ECMAscript2015
es7 = ECMAscript2016
es8 = ECMAscript2017
JavaScript包含
- 语言核心:
ECMAscript like 变量 数组 函数 对象……. - DOM 文档对象模型
- BOM 浏览器模型对象
优先级
(++ — !)> 数学>比较>逻辑>赋值
函数表达式
函数表达式也是定义函数的一种方式 比如
var sum = function(num1,num2) {
return num1 + num2;
}
等号右边的是一个没有名字的函数(匿名函数)
习题:反转整数
function rev(a) {
var b = 0;
while(a) {
b = b*10 + a%10;
a = parseInt(a/10);
}
return b;
}
alert(rev(6500)); // 6500 56
作用域链
近水楼台先得月
隐式全局变量
不写var的自动成为全局变量
闭包
定义:
一个函数可以把它内部的语句,和自己声明时所处的作用域一起封装成了一个密闭的环境,我们将这封闭的环境成为闭包。
每个函数都是闭包,每个函数天生能够记忆自己定义时所处的作用域
性质:
每次重新引用函数,那么闭包是全新的。
数组
数组中常用方法
数组的头尾操作
push 插到尾巴上
pop 删除尾巴一个,并返回该元素
unshift 插到头上
shift 在开头删除
数组的合并拆分
合并:
arr = arr.concat(arr2,[“…”]);
截取:
arr2 = arr.slice(1,5);
截取index为1~4的元素组成新数组,不包含5。
arr3 = arr.slice(2);
从角标2开始一直截取到数组末尾
arr4 = arr.slice(-4, -2);
从倒数第4项到倒数第三项,不包括倒数第二项。
arr4 = arr.slice(-4);
从倒数第4项到末尾。
arr4 = arr.slice(4, 2);
产生空数组。
这两方法都不会对原数组产生影响。
数组反转
arr.reverse();
splice: 插入删除替换
arr.splice(3,2,”x”,”y”,”z”);
将arr数组的index为3和4的元素替换为”x”,”y”,”z”。
能插能删能替换,简直全能!
join
在数组元素之间插入某个东西,然后返回一个字符串。
sort
排字母正常;
排数字不正常,因为会先把数字变成字符串再排。
所以,更新一下sort。
自定义一下规则。
arr2.sort(function(a, b){
if(a<b){
return -1;
} else if(a==b){
return 0;
} else {
return 1;
}
});
这样,就可以升序排列数字啦!
结合函数观察闭包
案例一
for(var i=0; i<10; i++) {
arr[i] = function() {
alert(i);
}
}
arr0;//10
arr2;//10
arr5;//10
为什么?
闭包只能说它认识这个i,而i在变化。只是记住这个变量,而不是记住变量的值!i的值以用的时候为准。
案例二
for(var i=0; i<10; i++) {
(function(n) {
arr[n] = function() {
alert(n);
}
})(i);
}
为什么?
每一个arr在赋值的时候,它都放在IIFE里面,IIFE天生隔离作用域。每一次循环都相当于在for大域里面建立一个新的IIFE小域,每个小域之间彼此隔离。
字符串
属性
length
方法
charAt()
返回指定位置的字符
concat()
“abc”.concat(“lmn”);
indexOf()
检索字符串
“人人都爱人民币”.indexOf(“人”);//0
lastIndexOf()
“人人都爱人民币”.lastIndexOf(“人”);//4
replace()
替换
“hhhjjjsasjk”.replace(“h”, “1”);
//1hhjjjsasjk
slice()
提取
“人人都爱人民币”.slice(-3, -1);
//“人民”
substr()
截取子串
“abcfhh123”.substr(3,6);
//从下标为3的地方开始截取6个字符
substring()
截取字符串
“abcfhh123”.substring(3,6);
//“fhh”
//从下标为3的地方开始,截取到下标为5的位置
toLowerCase()
toUpperCase()
arguments对象
js没有函数重载!
js在遇到两个函数名一样的情况下,它不管你的参数个数有什么不同,下面的覆盖上面的函数。
实验证明:
每个函数都有一个arguments对象,该对象将来会接受用户传入的所有的实参。
arguments不是数组是类数组,类似于数组,是对象。
arguments涵盖了所有的实参。
用arguments模拟函数重载
arguments.length
IIFE
名词解释:
- 函数自执行表达式
- 即时调用函数表达式
- 函数在定义的时候就想直接调用之
用法
只有表达式才可以用()来执行
(function myfunc() {
alert(“hehe”);
})();//hehe
myfunc();//报错
那么干脆不写函数名字。
标准的形式
(function () {
alert(“hehe”);
})();//hehe
本质是个表达式,有值。
JSDOM
一切皆节点:标签节点、属性节点、文本节点
html最大。
查找元素
document.getElementById()
document.getElementsByTagName()
document.body
使用第二个方法找div会找到多个div,我们想改变第三个div的内容怎么办?
var divs = document.getElementsByTagName(“div”);
divs[2].innerHTML = “今天是最后一天”;
document.getElementsByTagName()结果是个类数组。就算取得的只有一个元素,也要当数组用!
id是区分大小写,但是IE6 7 8不区分
IE7以及较低的版本,表单元素name特效也会被当做id
document.getElementById(“he”)
document属性
document.title 就是tab标题啊!
document.URL 当前文档路径
更改html属性
js可以更改html任何属性,方法有两种:
- “.”语法
- 一般属性原封不动的写
- 对于元素的class属性,应该使用.className
- 对于for属性,要写成.htmlFor
- 对于rowspan,要写成rowSpan
- 对于colspan ,要写成colSpan
- 对自定义属性无效
- 所有的行内样式,.style得到的是一个样式对象,继续通过打点得到的是小样式;
- 点语法效率要高于后者,除了获取自定义属性之外,一般都用点语法。
- setAttribute()和getAttribute()
- 对自定义属性有效
- getAttribute(“style”)得到的是字符串;
- 通过方法获得属性,不需要避讳:类似class变className酱紫。
操作元素样式
元素.style得到所有样式的封装,注意打点只能获得行内式!
js双引号里面,原来css怎么写就怎么写
事件
事件三要素
事件源
谁身上发生的行为(名词)什么行为
比如单击事件处理程序
行为发生后怎么处理?
常见的事件
- onclick 单击
- onmouseover 鼠标进入
- onmouseout 鼠标离开
- ondblclick 鼠标双击
- onfocus 得到焦点
- onblur 失去焦点
- onmousedown
- onmouseup
window.onload = function(){}
当页面加载完成后再去执行函数里面的东西;
document.getElementsByTagName()允许连续找,连续get。
批量添加事件会产生序号闭包问题,如何解决?
- 函数内使用this来代替divs[i];
- 或者使用IIFE包裹绑定事件:
原因是匿名函数天生具有封闭作用域; - 给元素强制添加属性,使用this.index代替i:
for(var i=0; i<divs.length;i++){ divs[i].index = i;
divs[i].onclick = function(){
divs[this.index].style.color = "yellow";
}
}
计算后的样式
DOM提供了可靠的api,得到计算后的样式。
W3C指定的标准api,IE9+实现了window.getComputedStyle()
,该方法接受一个要进行样式计算的元素,返回值是一个样式对象,该样式对象提供了一个getPropertyValue()
方法,帮我们得到特定样式属性的计算样式。
// 获取p元素宽度
var oP = document.getElementById("box");
//alert(oP.style.width); 返回空 只能操作行内样式
var w = window.getComputedStyle(oP).getPropertyValue("width");
// 或
var w = getComputedStyle(oP).getPropertyValue("width"); window可以省略
alert(w);
- 凡是window对象下的方法或者属性,使用时,window都可以省略!
- getPropertyValue(“box-size”) 双引号里面的参数要使用css属性,不能写驼峰式名字!
- 可以不用 getPropertyValue(“box-size”) 这个方法来获得样式属性。直接用[“box-size”]或者[“bosSize”]。此时双引号里面驼峰式命名法和css属性命名法皆可。getComputedStyle(oP)[“属性”]
- 对于IE6/7/8不兼容getPropertyValue(“box-size”) ,IE6/7/8有自己的一套写法: 元素.currentStyle.属性(驼峰式)
oP.currentStyle.boxSize
或者 元素.currentStyle.[“属性”] (可驼可不驼)
oP.currentStyle[“boxSize”]
总结
尽量用总括号,免得记来记取。
问题:
IE不认识getComputedStyle(oP)
Chrome不认识
currentStyle属性
解决
var oDiv = document.getElementsByTagName(“div”)[0];
if(window.getComputedStyle){
alert(getComputedStyle(oDiv)[“paddingLeft”]);
} else {
alert(oDiv.currentStyle.paddingLeft);
}
自己封装一个函数,函数的功能是求某个元素的属性值
<script type="text/javascript">
//定义函数
console.log("正常");
function fetchComputedStyle(obj,property){
//用户输入的属性有两种情况
//驼峰式或者css传统写法
//高版本下将驼峰式变为css传统属性写法
if (window.getComputedStyle) {
property = property.replace(/([A-Z])/g, function(match,$1){
return "-" + $1.toLowerCase();
});
console.log(window.getComputedStyle(obj)[property]);
} else {
//低版本下,将css传统写法变成驼峰式
property = property.replace(/\-([a-z])/g, function(match,$1){
return $1.toUpperCase();
});
console.log(obj.currentStyle[property]);
}
}
var oDiv = document.getElementsByTagName("div")[0];
fetchComputedStyle(oDiv,"paddingLeft");
</script>
透明度
IE8及以前的版本不支持opacity,js是通过obj.style.opacity或obj.currentStyle.opacity,返回的依然是opacity值,只要保持opacity与filter设置一样便可!
//不兼容写法
opacity: .2;
//兼容写法
opacity: .2;
filter: alpha(opacity=20);
获取透明度属性
//高版本
getComputedStyle(oDiv)[“opacity”];
//低版本
oDiv.currentStyle.opacity;
offsetLeft属性和offsetTop属性
兼容性非常差
通过oDiv.offsetLeft获取
对于IE9+、Chrome等高级浏览器,某个元素的offsetLeft值,是这个元素的左边框外到自己的offsetParent对象的左边框内的距离。
所以,要想知道元素的offsetLeft值的话,必须先知道元素的offsetParent究竟是谁。
offsetParent:
通过oDiv.offsetParent.className获取
对于IE9+、Chrome等高级浏览器:
自己祖先元素中,离自己最近的且定位的元素,假如祖先元素都没有定位,那么offsetParent对象便是body。 和自己有没有定位没有关系。IE8:
和高级浏览器大致一样。自己祖先元素中,离自己最近的且定位的元素。但是多算了一条边框。- 对于IE6 7:
- 如果自己没有定位属性,那么自己的offsetParent对象就是离自己最近的祖先元素含有width或height的元素;
- 如果自己有定位属性,则自己的offsetParent属性就是离自己最近的并且定位的元素。
兼容性解决方案
自定位,父无边。
offsetWidth属性和offsetHeight属性
全线兼容 !
自己的属性,和别的盒子无关。
通过oDiv.offsetWidth获取。
offsetWidth = 左右两侧border + width + 左右padding
offsetHeight = 上下border + height + 上下padding
假如盒子没有宽度,此时所有浏览器会把px当做offsetWidth;
假如盒子没有高度,用文字撑开。
clientWidth属性和clientHeight属性
全线兼容!IE6有点问题。。。
通过oDiv.clientWidth获取。
clientWidth = 左右padding + width
假如盒子没有宽度,此时所有浏览器会把px当做clientWidth;
假如盒子没有高度,用文字撑开。IE6 之clientHeight值是0,其他浏览器都是数字。
运动
定时器
window对象有一个方法setInterval(函数,时间间隔)
setInterval(func,2000ms);//ms不要写
//或
setInterval(“func()”,2000ms);//ms不要写
//或
setInterval(func(){},2000ms);//ms不要写
取消定时器
clearInterval(timer);
其中timer是定时器的引用,是个全局变量,创建定时器时曾赋值给这个变量。
运动需要注意的地方
btn_start.onclick = function(){
timer = setInterval( function(){
num += 4;
box.style.left = num + “px”;
}, 30);
}
连续点击按钮多次,物体运动越来越快,为什么?
因为有多个定时器在起作用,效果叠加。
如何解决?
先取消原来存在的定时器,然后重新开启。like this:
btn_start.onclick = function(){
clearInterval(timer);
timer = setInterval( function(){
num += 4;
box.style.left = num + “px”;
}, 30);
}
技巧
拉终停表,让盒子达到希望的位置后停止。
如何制作无缝滚动条?
使用【戏法】- 偷天换日!
JSON
JavaScript object notation
js对象表示法
由JavaScript界大神:道格拉斯自创
json语法
{
“k”:v,
“k”:v,
“k”:v
}
如何使用?
- 点语法;
- 中括号里面加双引号
json还可以嵌套
感觉跟使用对象差不多!
json还可以添加或者删除属性
person.hobby = [“teaching”, “coding”, “reading”];
alert(person.hobby[1];//teaching
delete person.wife;
json的循环遍历
for(var k in person){
alert(k);
}
引入外部js要注意的问题
- 先引包,再调用;
- 如果要先用后引包,则须得将调用函数放到window.onload = function(){}表示窗口加载完毕再执行。
异步和回调函数
同步
js如果没有特殊结构,一般是同步的,前面的语句执行完了之后再执行后面的语句。
异步
js如若遇到特殊结构,(setInterval、setTimeout、ajax、node、事件绑定),不必傻等,继续后面的操作。
apply和call
函数可以通过apply和call语句来指定内部的this指向。
function fn(){
console.log(this);
console.log(this.innerHTML);
}
fn.call(oDiv[0]);
call作用
- 可以调用函数;
- 改变函数内部this的指向为小括号里面的参数;
apply作用
fn.apply(oDiv[0]);作用和call一样!
两者区别
传参方式不同
function fn(x,y,z){
console.log(x+y+z);
console.log(this);
}
fn.call(oDiv[0],2,3,4);
fn.apply(oDiv[0],[2,3,4]);
setTimeout
只执行一次。
函数节流
函数有时候会设置给一些事件,事件可能被频繁的调用,函数会在短时间内执行多次,就可能会影响其他函数执行
JavaScript高级
面向对象
什么是对象
有狭义广义之分
狭义对象
指的是用花括号{}定义的对象,键值对,它是一组无序的属性集合。
数组也可以存储一组数据,但是不能更好的表达语义。
广义对象
万物皆为对象。
- 正则表达式、函数、DOM、数组、window、document、Math、Date、Number、String都是对象
- 基本类型不是对象
对象和json的区别
- json一定是对象,而对象不一定是json
- 对象中如若键名不符合命名规范,那么就必须要加双引号,访问该属性时也必须使用[“”]形式,不能用点语法
- js中[]能将变量转化为字符串
对象的方法
假如某个对象的某个属性是一个函数,我们把这个属性成为这个对象的方法。
函数上下文
- 当一个函数被当做对象的方法被调用时:
obj.fuc()
,这个函数里的this指的就是该对象。 var fn = obj.fuc; fn();
此时,this == window。
总结
- 函数上下文是什么,取决于函数如何被调用,而不是函数如何定义;
- 函数直接圆括号调用,上下文就是window;
- 当一个函数被当做对象的方法被调用时,这个函数的上下文就是该对象;
- 如果函数是事件处理函数,上下文就是触发了这个事件的对象;
- 定时器调用函数,上下文就是window;
- 数组存放的函数,被数组索引之后加圆括号调用,上下文就是该数组。
callee是什么
function fn(){
alert(arguments.callee === fn);//true
alert(arguments.callee.length);//形参个数
alert(arguments.length);//实参个数
}
new
作用
- 调用函数
- 构造函数,返回一个对象:
- 在真正执行函数体之前,函数内部先默认创建一个局部变量,是一个空对象;
- 让函数体内部的this指向这个空对象,而不是window;
- 执行函数体;
- 函数体全部执行完毕,函数会返回该对象,返回函数上下文。
构造函数首字母一般大写!
构造函数里面使用return:
- 如果返回基本类型,则无视这个return,该return谁就return谁,但是return会阻止这个函数;
- 如果return一个引用类型的话,如{}、[]、正则、函数、DOM、Math等,则会覆盖原有,构造出来的对象以你返回的为主。
原型链
定义
所有的构造函数都有一个属性prototype,它指向的是构造函数的原型。当你使用构造函数new出一个实例的时候,这个实例会有一个属性_proto_,它指向的是构造函数的prototype,就是指向所谓的自己原型对象。
三角关系
构造函数的prototype指向谁,new出来的对象的__proto__就指向谁
原理
- 将来可以被构造函数new出来的实例对象访问。
计算机先看实例的构造函数中有没有say方法,假如没有,就会通过自己的__proto__查找构造函数的原型,原型上有say方法就会执行。
- 方法定义在构造函数.prototype原型上,将来new出来的对象(实例)。__proto__会指向原型对象,就可以用这个方法了,所有对象共用此方法,完全等价。
任何函数天生都有prototype,它是一个空对象。
继承
将父类的prototype赋值给子类的prototype。
for in 能找到对象的所有属性,包括原型链上的。
hasOwnProperty
任何object都能用。因为它定义在Object.prototype上。
它就找对象本身是否有该属性,不去原型链上找。
不能用一看到undefined就判断该属性不存在!有可能该属性的值就是undefined。
instanceOf
访问一个对象原型链上的每个原型对象,假如遍历到的这个原型对象是某个构造函数的prototype,则认为是这个构造函数的实例。
组件化开发
Date
date.getFullYear()
date.getMonth()//从0开始计数,结果加一才是真实月份
date.getDate()//日
date.getDay()//0~6 星期几
date.getHours()
date.getMinutes()
date.getSeconds()
date.getMilliseconds()
Date.parse("2017-08-09")