JavaScript杂项

107 阅读5分钟

call apply bind 总结

相同点

都可以改变函数内部的this指向。

区别点

  1. callapply 会调用函数,并且改变函数内部的this指向
  2. callapply 传递的参数不一样,call传递参数 arg1,arg2..形式, apply必须数组形式[args]
  3. bind 不会调用函数,可以改变函数内部的this指向

主要应用场景

  • call 经常做继承
  • apply 经常跟数组有关系,比如借助于数学对象实现最大值和最小值
  • bind 不调用函数,但是还想改变this指向,比如改变定时器内部的this指向

严格模式

JavaScript除了提供正常模式外,还提供了严格模式strict modeES5的严格模式是采用具有限制性JavaScript变体的一种方式,即在严格的条件下运行JS代码。

严格模式在IE10以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。

严格模式对正常的JavaScript语义做了一些更改:

  1. 消除了Javascript语法的一些不合理、不严谨之处,减少了一些怪异行为。

  2. 消除代码运行的一些不安全之处,保证代码运行的安全。

  3. 提高编译器效率,增加运行速度。

  4. 禁用了在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;
      }
   }

}