new 操作符干了什么?

  • 创建一个新对象
  • 对象连接到构造函数原型上
  • 执行构造函数代码,并绑定 this(为这个新对象添加属性)
  • 返回新对象

    手写简版new函数

    1. function myCreate() {
    2. // 创建一个空对象
    3. const obj = new Object()
    4. // 获取到构造器
    5. const constructor = Array.from(arguments).shift();
    6. // 继承构造器上原型
    7. obj.__proto__ = constructor.prototype;
    8. // 通过call函数将this绑定到obj上,并添加属性
    9. constructor.call(obj, ...Array.from(arguments).slice(1))
    10. // 返回this
    11. return obj;
    12. }
    更简版
    1. function yourCreate(constructor, ...args){
    2. const obj = Object.create(constructor.prototype);
    3. constructor.apply(obj,args)
    4. return obj
    5. }

    使用

    ```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()

  1. <a name="hFyrL"></a>
  2. ### 实现Instanceof方法
  3. 大概思路就是能否目标对象原型链上查找到需判断的构造函数
  4. ```javascript
  5. function myInstanceof(targetObj, ctor) {
  6. // 如果是基本数据类型直接返回
  7. if (typeof targetObj !== 'object' || targetObj === null) {
  8. return false
  9. }
  10. // 获取目标对象原型
  11. let proto = Object.getPrototypeOf(targetObj)
  12. // 判断原型对象上的构造函数 与需要检查的构造函数是否相同
  13. if (proto.constructor === ctor) return true
  14. // 在原型链上查找是否存在需要判断的构造函数
  15. while (proto !== null) {
  16. if (proto.constructor === ctor) return true
  17. proto = Object.getPrototypeOf(proto)
  18. }
  19. return false
  20. }
  21. class Aaa extends Array {
  22. constructor(name){
  23. super()
  24. this.name = name
  25. }
  26. }
  27. 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, …)

  1. <a name="SlVQq"></a>
  2. ### 手写简版call方法
  3. ```javascript
  4. Function.prototype.yourCall = function(){
  5. //获取需绑定的上下文
  6. const target = Array.from(arguments).shift();
  7. // 获取传入的参数
  8. const args = Array.from(arguments).slice(1);
  9. // 使用Symbol创建key,防止属性覆盖
  10. const key = Symbol('key')
  11. // 在上下文添加this 此处的this为调用yourCall的函数
  12. target[key] = this;
  13. // 简单理解谁调用函数 this则指向谁
  14. target[key](...args)
  15. delete target[key]
  16. }
  17. const fn = function(name,age,gender){
  18. this.name = name;
  19. this.age = age;
  20. this.gender = gender;
  21. }
  22. const person = {}
  23. fn.yourCall(person, "长青", 23, true)
  24. console.log(person)

手写简版apply方法

思路与 call 方法一直,只是传参的方式不一样。

  1. Function.prototype.yourApply = function(){
  2. //获取需绑定的上下文
  3. const target = Array.from(arguments).shift();
  4. // 获取传入的参数
  5. const args = Array.from(arguments)[1] || [];
  6. // 使用Symbol创建key,防止属性覆盖
  7. const key = Symbol('key')
  8. // 在上下文添加this 此处的this为调用yourCall的函数
  9. target[key] = this;
  10. // 简单理解谁调用函数 this则指向谁
  11. target[key](...args)
  12. delete target[key]
  13. }
  14. const fn = function(name,age,gender){
  15. this.name = name;
  16. this.age = age;
  17. this.gender = gender;
  18. }
  19. const person = {}
  20. fn.yourApply(person,['长青',23, true])
  21. console.log(person)

手写简版bind方法

思路和上面差不多,只不过call、apply在绑定this的同时执行了函数,bind在绑定this后返回了该函数

  1. Function.prototype.yourBind = function () {
  2. const target = Array.from(arguments).shift();
  3. const args = Array.from(arguments).slice(1);
  4. const key = Symbol('key');
  5. target[key] = this;
  6. return function () {
  7. target[key](...args)
  8. delete target[key]
  9. }
  10. }
  11. function print() {
  12. console.log(this)
  13. }
  14. const person = {name: '长青'}
  15. const myPrint = print.yourBind(person)
  16. myPrint()