JavaScript深切之new的模仿完成

JavaScript深切系列第十二篇,经由过程new的模仿完成,带人人揭开运用new取得组织函数实例的原形

new

一句话引见 new:

new 运算符竖立一个用户定义的对象范例的实例或具有组织函数的内置对象范例之一

或许有点难明,我们在模仿 new 之前,先看看 new 完成了哪些功用。

举个例子:

// Otaku 御宅族,简称宅
function Otaku (name, age) {
    this.name = name;
    this.age = age;

    this.habit = 'Games';
}

// 由于缺少磨炼的原因,身材强度让人担心
Otaku.prototype.strength = 60;

Otaku.prototype.sayYourName = function () {
    console.log('I am ' + this.name);
}

var person = new Otaku('Kevin', '18');

console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60

person.sayYourName(); // I am Kevin

从这个例子中,我们能够看到,实例 person 能够:

  1. 接见到 Otaku 组织函数里的属性

  2. 接见到 Otaku.prototype 中的属性

接下来,我们能够尝试着模仿一下了。

由于 new 是关键字,所以没法像 bind 函数一样直接掩盖,所以我们写一个函数,命名为 objectFactory,来模仿 new 的效果。用的时刻是如许的:

function Otaku () {
    ……
}

// 运用 new
var person = new Otaku(……);
// 运用 objectFactory
var person = objectFactory(Otaku, ……)

开端完成

剖析:

由于 new 的效果是一个新对象,所以在模仿完成的时刻,我们也要竖立一个新对象,假定这个对象叫 obj,由于 obj 会具有 Otaku 组织函数里的属性,想一想典范继续的例子,我们能够运用 Otaku.apply(obj, arguments)来给 obj 增加新的属性。

在 JavaScript 深切系列第一篇中,我们便讲了原型与原型链,我们晓得实例的 __proto__ 属性会指向组织函数的 prototype,也恰是由于竖立起如许的关联,实例能够接见原型上的属性。

如今,我们能够尝试着写初版了:

// 初版代码
function objectFactory() {

    var obj = new Object(),

    Constructor = [].shift.call(arguments);

    obj.__proto__ = Constructor.prototype;

    Constructor.apply(obj, arguments);

    return obj;

};

在这一版中,我们:

  1. 用new Object() 的体式格局新建了一个对象 obj

  2. 掏出第一个参数,就是我们要传入的组织函数。另外由于 shift 会修正原数组,所以 arguments 会被去除第一个参数

  3. 将 obj 的原型指向组织函数,如许 obj 就能够接见到组织函数原型中的属性

  4. 运用 apply,转变组织函数 this 的指向到新建的对象,如许 obj 就能够接见到组织函数中的属性

  5. 返回 obj

更多关于:

原型与原型链,能够看《JavaScript深切之从原型到原型链》

apply,能够看《JavaScript深切之call和apply的模仿完成》

典范继续,能够看《JavaScript深切之继续》

复制以下的代码,到浏览器中,我们能够做一下测试:

function Otaku (name, age) {
    this.name = name;
    this.age = age;

    this.habit = 'Games';
}

Otaku.prototype.strength = 60;

Otaku.prototype.sayYourName = function () {
    console.log('I am ' + this.name);
}

function objectFactory() {
    var obj = new Object(),
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    Constructor.apply(obj, arguments);
    return obj;
};

var person = objectFactory(Otaku, 'Kevin', '18')

console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60

person.sayYourName(); // I am Kevin

[]~( ̄▽ ̄)~**

返回值效果完成

接下来我们再来看一种状况,假如组织函数有返回值,举个例子:

function Otaku (name, age) {
    this.strength = 60;
    this.age = age;

    return {
        name: name,
        habit: 'Games'
    }
}

var person = new Otaku('Kevin', '18');

console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // undefined
console.log(person.age) // undefined

在这个例子中,组织函数返回了一个对象,在实例 person 中只能接见返回的对象中的属性。

而且还要注重一点,在这里我们是返回了一个对象,假如我们只是返回一个基础范例的值呢?

再举个例子:

function Otaku (name, age) {
    this.strength = 60;
    this.age = age;

    return 'handsome boy';
}

var person = new Otaku('Kevin', '18');

console.log(person.name) // undefined
console.log(person.habit) // undefined
console.log(person.strength) // 60
console.log(person.age) // 18

效果完整倒置过来,此次只管有返回值,然则相当于没有返回值举行处置惩罚。

所以我们还需要推断返回的值是否是一个对象,假如是一个对象,我们就返回这个对象,假如没有,我们该返回什么就返回什么。

再来看第二版的代码,也是末了一版的代码:

// 第二版的代码
function objectFactory() {

    var obj = new Object(),

    Constructor = [].shift.call(arguments);

    obj.__proto__ = Constructor.prototype;

    var ret = Constructor.apply(obj, arguments);

    return typeof ret === 'object' ? ret : obj;

};

下一篇文章

JavaScript深切之类数组对象与arguments

相干链接

《JavaScript深切之从原型到原型链》

《JavaScript深切之call和apply的模仿完成》

《JavaScript深切之继续》

深切系列

JavaScript深切系列目次地点:https://github.com/mqyqingfeng/Blog

JavaScript深切系列估计写十五篇摆布,旨在帮人人捋顺JavaScript底层学问,重点解说如原型、作用域、实行上下文、变量对象、this、闭包、按值通报、call、apply、bind、new、继续等难点观点。

假如有毛病或许不严谨的处所,请务必赋予斧正,非常谢谢。假如喜好或许有所启示,迎接star,对作者也是一种勉励。

    原文作者:冴羽
    原文地址: https://segmentfault.com/a/1190000009286643
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞