思路

new一个对象的过程:

  1. 首先创建一个空对象
  2. 设置原型:把这个空对象的原型设置为构造函数的prototype属性
  3. 绑定this:让构造函数的this指向这个对象
  4. 添加属性:执行构造函数内部的代码(为这个新对象添加属性)
  5. 判断构造函数的返回值类型:

(1)如果构造函数没有返回值,则实例对象就是新创建的obj (2)如果构造函数有返回值,但返回值不是一个对象,那么实例对象还是新创建的obj

  1. function Person() {
  2. ...
  3. return 1
  4. }

(3)如果构造函数有返回值,且返回值是一个对象,那么实例对象不是新创建的对象obj了,而是显式return的这个对象

  1. function Person() {
  2. // 函数也是对象
  3. return function() {}
  4. }
  1. function _new() {
  2. // 截取第一个参数为构造函数
  3. let constructor = Array.prototype.shift.call(arguments)
  4. // 判断传入的是不是函数类型(构造函数)
  5. if (typeof constructor !== 'function') {
  6. console.error("type error");
  7. return
  8. }
  9. // 创建一个空对象,并把其原型设置为 构造函数的原型
  10. let newObj = Object.create(constructor.prototype)
  11. // 让构造函数的 this 指向 这个对象,并且执行构造函数的代码
  12. let result = constructor.apply(newObj, arguments)
  13. // 判断构造函数返回值类型
  14. let flag = result && (typeof result === "object" || typeof result === "function")
  15. return flag ? result : newObj
  16. }
  17. // test1
  18. function Person() {
  19. this.name = "mikasa"
  20. this.age = 16
  21. this.getName = function () {
  22. console.log(this.name);
  23. }
  24. }
  25. let person = _new(Person)
  26. console.log(person);
  27. // test2
  28. function Person(name, age) {
  29. this.name = name
  30. this.age = age
  31. this.getName = function () {
  32. console.log(this.name);
  33. }
  34. }
  35. // 构造函数后面为输入的参数
  36. let person = _new(Person, "mikasa", 16)

image.png

附加知识

apply改变this指向并执行构造函数代码
有关函数调用的知识看这里!!!
(apply 能够将特定函数当做一个方法绑定到指定对象上,并进行调用。属于动态调用的一种)

Function.apply(obj,args)方法能接收两个参数obj:这个对象将代替Function类里this对象args:这个是数组,它将作为参数传给Function(args—>arguments)

  1. function Person(name,age) {
  2. this.name=name;
  3. this.age=age;
  4. }
  5. function Student(name,age,grade) {
  6. Person.apply(this,arguments);
  7. this.grade=grade;
  8. }
  9. var student=new Student("zhangsan",21,"一年级");
  10. //test
  11. console.log(student)

image.png
这是为什么呢?学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢?
由于 apply 会 动态调用 函数
通俗一点讲就是: 用student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面