思路
new一个对象的过程:
- 首先创建一个空对象
- 设置原型:把这个空对象的原型设置为构造函数的prototype属性
- 绑定this:让构造函数的this指向这个对象
- 添加属性:执行构造函数内部的代码(为这个新对象添加属性)
- 判断构造函数的返回值类型:
(1)如果构造函数没有返回值,则实例对象就是新创建的obj (2)如果构造函数有返回值,但返回值不是一个对象,那么实例对象还是新创建的obj
function Person() {
...
return 1
}
(3)如果构造函数有返回值,且返回值是一个对象,那么实例对象不是新创建的对象obj了,而是显式return的这个对象
function Person() {
// 函数也是对象
return function() {}
}
function _new() {
// 截取第一个参数为构造函数
let constructor = Array.prototype.shift.call(arguments)
// 判断传入的是不是函数类型(构造函数)
if (typeof constructor !== 'function') {
console.error("type error");
return
}
// 创建一个空对象,并把其原型设置为 构造函数的原型
let newObj = Object.create(constructor.prototype)
// 让构造函数的 this 指向 这个对象,并且执行构造函数的代码
let result = constructor.apply(newObj, arguments)
// 判断构造函数返回值类型
let flag = result && (typeof result === "object" || typeof result === "function")
return flag ? result : newObj
}
// test1
function Person() {
this.name = "mikasa"
this.age = 16
this.getName = function () {
console.log(this.name);
}
}
let person = _new(Person)
console.log(person);
// test2
function Person(name, age) {
this.name = name
this.age = age
this.getName = function () {
console.log(this.name);
}
}
// 构造函数后面为输入的参数
let person = _new(Person, "mikasa", 16)
附加知识
apply改变this指向并执行构造函数代码?
有关函数调用的知识看这里!!!
(apply 能够将特定函数当做一个方法绑定到指定对象上,并进行调用。属于动态调用的一种)
Function.apply(obj,args)方法能接收两个参数obj:这个对象将代替Function类里this对象args:这个是数组,它将作为参数传给Function(args—>arguments)
function Person(name,age) {
this.name=name;
this.age=age;
}
function Student(name,age,grade) {
Person.apply(this,arguments);
this.grade=grade;
}
var student=new Student("zhangsan",21,"一年级");
//test
console.log(student)
这是为什么呢?学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢?
由于 apply 会 动态调用 函数
通俗一点讲就是: 用student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面