new 操作符干了什么?
- 创建一个新对象
- 对象连接到构造函数原型上
- 执行构造函数代码,并绑定 this(为这个新对象添加属性)
- 返回新对象
手写简版new函数
更简版function myCreate() {// 创建一个空对象const obj = new Object()// 获取到构造器const constructor = Array.from(arguments).shift();// 继承构造器上原型obj.__proto__ = constructor.prototype;// 通过call函数将this绑定到obj上,并添加属性constructor.call(obj, ...Array.from(arguments).slice(1))// 返回thisreturn obj;}
function yourCreate(constructor, ...args){const obj = Object.create(constructor.prototype);constructor.apply(obj,args)return obj}
使用
```javascript function Person(name, age, gender ) { this.name = name; this.age = age; this.gender = gender; }
Person.prototype.introduce = function () {
console.log(name: ${this.name}
age: ${this.age}
gender: ${this.gender? '男': '女'})
}
const human = myCreate(Person, ‘长青’, 23, true) human.introduce()
<a name="hFyrL"></a>### 实现Instanceof方法大概思路就是能否目标对象原型链上查找到需判断的构造函数```javascriptfunction myInstanceof(targetObj, ctor) {// 如果是基本数据类型直接返回if (typeof targetObj !== 'object' || targetObj === null) {return false}// 获取目标对象原型let proto = Object.getPrototypeOf(targetObj)// 判断原型对象上的构造函数 与需要检查的构造函数是否相同if (proto.constructor === ctor) return true// 在原型链上查找是否存在需要判断的构造函数while (proto !== null) {if (proto.constructor === ctor) return trueproto = Object.getPrototypeOf(proto)}return false}class Aaa extends Array {constructor(name){super()this.name = name}}console.log(myInstanceof(new Aaa('长青'), Array))
改变this的方法有哪些以及它们的区别
改变this的方法有 bind、 call、 apply,区别在于调用它们的方式不同
- apply:接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次。
- call方法的第一个参数也是this的指向,后面传入的是一个参数列表跟apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次
- bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)改变this指向后不会立即执行,而是返回一个永久改变this指向的函数
使用区别
```javascript function func(){} const thisArg = {}
func.call(thisArg, param1, param2, …)
func.apply(thisArg, [param1,param2,…])
func.bind(thisArg, param1, param2, …)
<a name="SlVQq"></a>### 手写简版call方法```javascriptFunction.prototype.yourCall = function(){//获取需绑定的上下文const target = Array.from(arguments).shift();// 获取传入的参数const args = Array.from(arguments).slice(1);// 使用Symbol创建key,防止属性覆盖const key = Symbol('key')// 在上下文添加this 此处的this为调用yourCall的函数target[key] = this;// 简单理解谁调用函数 this则指向谁target[key](...args)delete target[key]}const fn = function(name,age,gender){this.name = name;this.age = age;this.gender = gender;}const person = {}fn.yourCall(person, "长青", 23, true)console.log(person)
手写简版apply方法
思路与 call 方法一直,只是传参的方式不一样。
Function.prototype.yourApply = function(){//获取需绑定的上下文const target = Array.from(arguments).shift();// 获取传入的参数const args = Array.from(arguments)[1] || [];// 使用Symbol创建key,防止属性覆盖const key = Symbol('key')// 在上下文添加this 此处的this为调用yourCall的函数target[key] = this;// 简单理解谁调用函数 this则指向谁target[key](...args)delete target[key]}const fn = function(name,age,gender){this.name = name;this.age = age;this.gender = gender;}const person = {}fn.yourApply(person,['长青',23, true])console.log(person)
手写简版bind方法
思路和上面差不多,只不过call、apply在绑定this的同时执行了函数,bind在绑定this后返回了该函数
Function.prototype.yourBind = function () {const target = Array.from(arguments).shift();const args = Array.from(arguments).slice(1);const key = Symbol('key');target[key] = this;return function () {target[key](...args)delete target[key]}}function print() {console.log(this)}const person = {name: '长青'}const myPrint = print.yourBind(person)myPrint()
