一、call,apply,bind
-
call,apply,bind都是用于改变this指向的
-
区别:
-
传参不同
- call用逗号分隔的形式传参
函数名.call(目标对象,参数1,参数2,...参数n) 例如:getName.call(obj,'王五',25,'北京')
- apply参数用数组的形式传递
函数名.apply(目标对象,[参数1,参数2,...参数n]) 例如:getName.apply(obj,['王五11',25,'上海'])
- bind用逗号形式传参
getName.bind(obj,'王五11',25,'上海')() 或 getName.bind(obj)('王五11',25,'上海')
-
函数是否被执行
cal和apply是直接调用函数 bind是返回函数本身,如果要执行,必须再后面再加()调用 getName.bind(obj)()
-
-
call,apply实现原理
- call的实现原理(不用call,自己手动模拟实现一个call的功能)
- call是基于函数实现的
- 给作用的目标对象添加一个临时函数,处理赋值操作
- 接收参数处理
- 最后再删除这个临时函数
实例化对象=new 构造函数() //其中构造函数也称为类,一个类可以生成多个实例化对象
- call的实现原理(不用call,自己手动模拟实现一个call的功能)
var f1=new Function() // 其中的构造函数中 this === f1 永远相等
var p1=new Person() //其中的构造函数中 this === p1 永远相等
//call模拟实现原理代码:
Function.prototype.call2 = function (context) {
//目标对象
context = context || window;
//this===实例化的函数,函数本质上也是对象
//给context添加一个临时函数
context.fn = this;
//接收参数处理 arguments
console.log('arguments:',arguments)
var args = [];
for (var i = 1; i < arguments.length; i++) {
// ["arguments[0]", "arguments[1]", "arguments[2]"]
args.push('arguments['+i+']')
// args.push(arguments[i])
}
//传参执行context.fn()函数
eval('context.fn(' + args + ')')
//删除临时函数
delete context.fn
}
- apply实现原理
Function.prototype.apply2 = function (context,arr) {
//目标对象
context = context || window;
//this===实例化的函数,函数本质上也是对象
//给context添加一个临时函数
context.fn = this;
if (!arr) {
context.fn()
} else {
//接收参数处理 arguments
var args = [];
for (var i = 0; i < arr.length; i++) {
// ["arguments[0]", "arguments[1]", "arguments[2]"]
args.push('arr['+i+']')
// args.push(arguments[i])
}
//传参执行context.fn()函数
eval('context.fn(' + args + ')')
}
//删除临时函数
delete context.fn
}
- bind实现原理
二、new的特点
- new的特点
- new 一个构造函数,会自动reutrn一个实例化对象
- new完的实例化对象____proto___自动指向构造函数的prototype
- new构造函数传参自动赋值给当前实例化对象
三、防抖和节流
-
防抖
- 在固定的时间内没有触发事件,会在固定时间结束后触发,如果固定时间内触发事件了,会在延长固定时间再触发
- 防抖主要利用定时器实现
//用定时器实现防抖
function debounce(func,wait) {
var timer=null;
return function() {
//保存当前调用的dom对象
var _this=this;
//保存事件对象
var args=arguments;
clearTimeout(timer)
timer=setTimeout(function() {
func.apply(_this,args)
},wait)
}
}
-
节流:
-
无论在固定时间内是否有事件触发,都会按照固定时间规律触发
-
具体实现有两种方法
-
- 第一种:时间戳
//时间戳版本实现节流
function throttle(func,wait) {
//定义初始时间
var oldTime=0;
return function() {
var _this=this;
var args=arguments;
//当前时间戳
var newTime=+new Date();
//判断用当前时间减去旧的时间,如果大于wait指定的时间就会触发
if(newTime-oldTime>wait) {
//执行触发的函数
func.apply(_this,args)
//将旧时间更新
oldTime=newTime;
}
}
- 第二种:定时器
//时间戳版本实现节流
function throttle(func,wait) {
var timer=null;
return function() {
var _this=this;
var args=arguments;
if(!timer) {
timer=setTimeout(function() {
timer=null;
func.apply(_this,args)
},wait)
}
}
}
扩展:目前市面主流工具函数库:lodash已经提供了全面的工具方法
//安装
npm install lodash
//引入
import _ from 'lodash'