【大白话】说JS的实际应用之箭头函数、this、new 、(call ,apply, bind)

104 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情

前言

大白话说JS内容包括:DOM的一些操作,Promise相关, 微任务宏任务,作用域,变量提升,闭包,变量类型,深浅拷贝,原型和作用域链,后续争取把js重点都记录上,深入浅出。

箭头函数和普通函数区别

箭头函数没有自己的this,他的this指向定义时所在的外层第一个普通函数,且 this指向永远不会改变,call、apply、bind 并不会影响其 this 的指向 在这里插入图片描述 没有原型prototype,不能作为构造函数使用(构造函数的this要是指向创建的新对象,但是箭头的this不会变),不能new,new了就报错

箭头函数没有自己的arguments参数,他的参数是外层普通函数的,取而代之用rest参数...代替arguments对象,来访问箭头函数的参数列表

let a = () => {};
console.log(a.prototype); // undefined

function a() {};
console.log(a.prototype); // {constructor:f}

let obj = {
  a: 10,
  b: () => {
    console.log(this); // window
  },
  c: function() {
    console.log(arguments); 
    console.log(this); // {a: 10, b: ƒ, c: ƒ}
  }
}
obj.b(); 
obj.c();

// rest参数...
let C = (...c) => {
  console.log(c);
}
C(3,82,32,11323);  // [3, 82, 32, 11323]

this指向

  1. 默认是全局对象:window(普通函数调用和定时器函数指向也是window)
  2. 被构造函数调用时,,this指向该对象(谁调用指向谁)
  3. 对象的方法调用(绑定事件同理), this 指向该方法所属的对象

更改this指向:call() ,apply(),bind()

new操作符原理

  1. 创建一个类的实例:创建一个空对象obj,然后把这个空对象的__proto__设置为构造函数的prototype。
  2. 初始化实例:构造函数被传入参数并调用,关键字this被设定指向该实例obj。
  3. 返回实例obj。

call ,apply, bind 方法及手写

这三个方法都是改变函数的this指向,期中call ,apply方法一样,只是传入的参数不同,详情见下面栗子,bind只是将结果以函数返回,接收后在调用即可,整体都是采用:B对象.方法.call(A,"参数")形式,表现为A对象要调用B的方法,下面看例子。

let dog = {
  name: "小狗",
  can (p1, p2) {
    console.log('我会' + p1 + p2);
  }
}

let cat = {
  name: "小猫"
}

// dog.can.call(cat, "睡觉", "钓鱼");
// dog.can.apply(cat, ["睡觉", "钓鱼"]);
let fn = dog.can.bind(cat, "睡觉", "钓鱼");
fn();

不难看出 call ,apply, bind 的整体使用相差无几,根据原理,怎么手写该类方法呢?

Function.prototype.myCall = function(context){
	if(typeof this !== "function"){
		throw new TypeError("Error")
	}
	context = context || window
	context.fn = this
	const args = [...arguments].slice(1)**加粗样式**
	const result = context.fn(...args)
	delete context.fn
	return result
}

Function.prototype.myApply = function(context){
	if(typeof this !== "function"){
		throw new TypeError("Error")
	}
	context = context || window
	context.fn = this
	let result
	if(arguments[1]){
		result = context.fn(...arguments[1])
	}else{
		result = context.fn()
	}
	delete context.fn
	return result
}

Function.prototype.myBind = function(context){
	if(typeof this !== 'function'){
		throw new TypeErroe('Error')
	}
	const _this = this
	const args = [...arguments].slice(1)
	return functions F(){
		if(this instanceof F){
			return new _this(...args,...arguments)
		}
		return _this.apply(context,args.concat(...arguments))
	}
}