call apply bind 总结
相同点
都可以改变函数内部的this指向。
区别点
call和apply会调用函数,并且改变函数内部的this指向call和apply传递的参数不一样,call传递参数arg1,arg2..形式,apply必须数组形式[args]bind不会调用函数,可以改变函数内部的this指向
主要应用场景
call经常做继承apply经常跟数组有关系,比如借助于数学对象实现最大值和最小值bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向
严格模式
JavaScript除了提供正常模式外,还提供了严格模式strict mode。ES5的严格模式是采用具有限制性JavaScript变体的一种方式,即在严格的条件下运行JS代码。
严格模式在IE10以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。
严格模式对正常的JavaScript语义做了一些更改:
-
消除了
Javascript语法的一些不合理、不严谨之处,减少了一些怪异行为。 -
消除代码运行的一些不安全之处,保证代码运行的安全。
-
提高编译器效率,增加运行速度。
-
禁用了在
ECMAScript的未来版本中可能会定义的一些语法,为未来新版本的Javascript做好铺垫。比如一些保留字如:class,enum,export,extends,import,super不能做变量名。
<script>
'user strict'
// 下面的JS代码就会按照严格模式执行
</script>
<script>
function(){
'use strict';
//该函数内的JS代码会按照严格模式执行
}
</script>
严格模式的主要变化
- 变量必须先声明才能使用
- 普通模式直接使用变量,相当于从
window对象添加属性,严格模式下不行
- 普通模式直接使用变量,相当于从
- 全局作用域中的函数
this指向不再是window,而是undefined - 构造函数不使用
new关键字则无法使用 - 函数中不能有同名的形参,从来不知道原来以前可以
- 函数必须声明在顶层,新版本
javascript会引入块级作用域,为了与新版本接轨,不允许在非函数代码块中声明函数
高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数,或者将函数作为返回值
数组新增方法
遍历(forEach)
var arr = [1,2,3,4,5,6,7,8];
var num = 0;
arr.forEach(function(value,index,array){
//遍历数组
//value:数组当前元素
//index:数组当前索引
//array:数组本身
num+=value;//例:求和
});
//返回值为null
console.log(num);
过滤(filter)
var arr = [1,2,3,4,5,6,7,8];
arr.filter(function(value,index,array){
//value:数组当前元素
//index:数组当前索引
//array:数组本身
//回调函数中返回一个布尔值,布尔值为true时,当前元素会进入新数组返回
return value>2;//例:获取数组中大于2的元素
});
//返回一个新的数组
查找存在(some)
var arr = [1,2,3,4,5,6,7,8];
arr.some(function(value,index,array){
//value:数组当前元素
//index:数组当前索引
//array:数组本身
return value>2;//例:数组中是否存在大于2的元素,符合条件立刻停止遍历并返回
});
//返回布尔值
全部符合(every)
var arr = [1,2,3,4,5,6,7,8];
arr.every(function(value,index,array){
//value:数组当前元素
//index:数组当前索引
//array:数组本身
return value>2;//例:数组中的元素是否全部大于2,是则返回true,否则false
});
//返回布尔值
汇总处理(reduce)
var arr = [1,2,3,4,5,6,7,8];
var sum = arr.reduce(function(pre,cur,index,array){
//pre:累计结果
//cur:数组当前元素
//index:数组当前索引
//array:数组本身
return pre+cur;//例:数组求和
},0);//这里的0为第一次回调中的pre
//返回累计结果
处理返回(map)
var arr = [1,2,3,4,5,6,7,8];
var newArr = arr.map(function(value,index,array){
//value:数组当前元素
//index:数组当前索引
//array:数组本身
return value*2;//例:遍历数组,把数组中的元素*2放入新数组并返回该数组
})
//返回一个新数组
对象方法
获取属性名
var obj = {
id:1,
name:'2',
age:17
}
var arr = Object.keys(obj);
//obj:目标对象
//获取obj对象所有的属性名
//返回值为数组
//arr = ["id", "name", "age"]
定义属性
var obj = {
id:1,
name:'2',
age:17
}
Object.defineProperty(obj, prop, descriptor)
//obj:目标对象
//prop:需要定义或修改的属性名
//descriptor:目标属性所拥有的特性
//descriptor参数说明
//参数以{}对象形式书写,该对象内部有四个属性
/*
value:设置属性的值,默认为undefined
writable:值是否可以重写,在新增属性时,默认为false
enumerable:目标属性是否可以被枚举,新增属性时,默认为false
configurable:目标实行是否可以被删除或是可以再次修改特性,新增属性时,默认为false
*/
Object.defineProperty(obj, 'prop', {//name属性值若存在,则修改;不存在,则新增
value:'wc',
writable:false,//不能通过 `对象.属性名=属性值` 进行修改,但可以通过这个方法修改
enumerable:false,//不能被遍历出来,如不能被 `Object.keys(obj)` 得到
configurable:false//不能被删除,也不能修改descriptor的参数即特性
})
闭包
闭包指有权访问另一个函数作用域中变量的函数
简单理解就是,一个作用域可以访问另一个函数内部的的局部变量
闭包的作用:延申了变量的作用范围
function fn(){//fn就是闭包函数
var num = 10;
function fun(){
console.log(num);//fun访问了fn的局部变量
}
//fun();
return fun;
}
var f = fn();
f();//外部访问
闭包案例
<ul>
<li>内容</li>
<li>内容</li>
<li>内容</li>
<li>内容</li>
</ul>
<script>
//实现:点击li,打印相应下标值
var lis = document.querySelectAll('li');
for(var i = 0; i<lis.length; i++){
//lis[i].index = i; 动态增加属性方法
//立即执行函数中的任何一个函数都可以使用它的变量
(function(index){
lis[i].onclick = function(){//该函数使用了上一个函数的变量,形成闭包
console.log(index);
}
})(i);
}
//在该案例中,闭包并不适合解决该问题,不如动态增加属性好用
</script>
深拷贝和浅拷贝
浅拷贝
//ES6中的新方法
var obj = {
id: 1,
msg: {
title: 'asd'
}
};
var o = {};
Object.assign(o,obj)
//其中两个msg为相同的引用
深拷贝
function deepCopy(newObj,oldObj){
for(var key in oldObj){
var item = oldObj[key];
if(item instanceof Array){//先判断数组是因为,数组也属于对象
newObj[key] = [];
deepCopy(newObj[key],item);
}else if(item instanceof Object){
newObj[key] = {};
deepCopy(newObj[key],item);
}else{
newObj[key] = item;
}
}
}