今天看啥  ›  专栏  ›  影子同学

[javaScript]new的使用与模拟实现

影子同学  · 掘金  ·  · 2020-04-03 06:34
阅读 38

[javaScript]new的使用与模拟实现

一、现象

new运算符可以创建构造函数的实例,使用方式如下:

function Student (name, className) {
    this.name = name;
    this.className = className;
    this.school = '人生有限学校'
    this.study = function () {
        console.log('努力学习')
    }
    var hello = 'hello'
}

Student.prototype.dayTime = 8;
Student.prototype.say = function () {
    console.log('my name is ' + this.name)
}

var s = new Student('hh', '高一3班');

console.log(s.name) //hh
console.log(s.school) //人生有限学校
console.log(s.dayTime) //8
s.study() //'努力学习'
s.sayYourName() //'my name is hh'
复制代码

由上可见,new创建出的实例:1.是一个对象 2.可以使用构造函数内部this添加的属性和方法 3.还可以使用构造函数的原型属性和方法

如果在构造函数里面有返回值呢,那么又是怎样一种表现呢:

//返回为一个对象
function Student (name, className) {
    this.name = name;
    this.className = className;
    this.age = 17
    return {
        name: name,
        sex: '女'
    }
}

let s = new Student('小易', '三年二班')
s.name //'小易'
s.className //undefined
s.age //undefined
s.sex //女

//返回基本类型
function Student (name, className) {
    this.name = name;
    this.className = className;
    this.age = 17
    return 'hello'
}

let d = new Student('小林', "三年七班")
s.name //'小林'
s.className //三年七班
s.age //17
s.sex //undefined
复制代码

通过上面的例子我们可以知道:4.如果构造函数显式返回的是一个对象,那么使用的是这个被返回的对象 5.如果显式返回的是基本类型,则使用的是忽略这段return语句的、本来就要返回的对象

二、模拟实现

new是关键字,是无法直接覆盖的。我通过写一个函数newFactory,来模拟new的效果let h = newFactory(Student, '小林', '三年二班')

思路分析:

通过第一段中得出的五点:

  1. 是一个对象
  2. 可以使用构造函数内部this添加的属性和方法
  3. 还可以使用构造函数的原型属性和方法
  4. 如果构造函数显式返回的是一个对象,那么使用的是这个被返回的对象
  5. 如果显式返回的是基本类型,则使用的是忽略这段return语句的、本来就要返回的对象

可以初步得到有(以let h = newFactory(Student, '小林', '三年二班')为例):

  1. 是一个对象 -> 创建一个新对象var obj = {}
  2. 可以使用构造函数内部this添加的属性和方法 -> 拿到构造函数后,将obj带入构造Student.apply(obj, ['小林', '三年二班'])
  3. 还可以使用构造函数的原型属性和方法 -> 即将该实例的原型指向该构造函数的原型obj.__proto__ = Student.prototype
  4. 如果构造函数显式返回的是一个对象,那么使用的是这个被返回的对象 -> 在步骤2中用变量res接受apply的返回结果var res = Student.apply(obj, ['小林', '三年二班']),如果res是一个对象,则返回res
  5. 如果显式返回的是基本类型,则使用的是忽略这段return语句的、本来就要返回的对象 -> 如果是基本类型,则返回obj

将这些思路凑起来,就有了:

function newFactory() {
    // 创建一个新对象
    var obj = {}
    // 获取构造函数(参数第一位),同时arguments会因去除第一个参数后,变成参数数组即['小林', '三年二班']
    Constructor = [].shift.call(arguments)
    // 将obj对象的原型指向构造函数的原型
    obj.__proto__ = Constructor.prototype
    // 执行,对obj对象进行加工操作并获得构造函数结果
    var res = Constructor.apply(obj, arguments)
    // 如果res为对象,返回res,否则返回obj
    return typeof res === 'object' ? res : obj
}
复制代码

三、总结

知道实现思路后,再自己手动实现的话就不会很难了

上面的对象初始化感觉还可以换种方式:

// old
var obj = {}
obj.__proto__ = Constructor.prototype

// new
var obj = Object.create(Constructor.prototype)
复制代码

少了一句话哈哈~




原文地址:访问原文地址
快照地址: 访问文章快照