菜单

JavaScript 深入的new的模仿实现

2018年11月16日 - JavaScript

JavaScript 深入的new的效仿实现

2017/05/26 · JavaScript
· new

原文出处: 冴羽   

已离开简书,原因参见
http://www.jianshu.com/p/0f12350a6b66。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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, ……)

1
2
3
4
5
6
7
8
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
2
3
4
5
6
7
8
9
10
11
12
13
14
// 第一版代码
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

[]~( ̄▽ ̄)~**

章好以本人之 Github
https://github.com/mqyqingfeng/Blog
查看

回值功能实现

连着下我们再次来拘禁一样栽情形,假如构造函数有归值,举个例:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

1
2
3
4
5
6
7
8
9
10
11
12
13
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; };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 第二版的代码
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深入系列目录地址:https://github.com/mqyqingfeng/Blog。

JavaScript深入系列预计写十五篇左右,旨在救助大家捋顺JavaScript底层知识,重点讲解如原型、作用域、执行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、继承等困难概念。

倘来错或未审慎的地方,请务必与指正,十分谢谢。如果喜欢或有启发,欢迎star,对笔者也是同栽鞭策。

本系列:

  1. JavaScirpt 深入的起原型到原型链
  2. JavaScript
    深入的词法作用域和动态作用域
  3. JavaScript 深入之实践上下文栈
  4. JavaScript 深入的变量对象
  5. JavaScript 深入之作用域链
  6. JavaScript 深入的从 ECMAScript 规范解读
    this
  7. JavaScript 深入的实践上下文
  8. JavaScript 深入之闭包
  9. JavaScript 深入的参数按值传递
  10. JavaScript
    深入之call和apply的仿实现
  11. JavaScript 深入之bind的法实现

    1 赞 1 收藏
    评论

图片 1

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图