Javascript模拟实现new原理解析


Posted in Javascript onMarch 03, 2020

new是JS中的一个关键字,用来将构造函数实例化的一个运算符。例子:

function Animal(name) {
  this.name = name;
}
Animal.prototype.sayName = function() {
  console.log("I'm " + this.name);
}
var cat = new Animal('Tom');
console.log(cat.name); // Tom
console.log(cat.__proto__ === Animal.prototype); // true
cat.sayName(); // I'm Tom

从上面的例子可以得出两点结论:

  • new操作符实例化了一个对象;
  • 这个对象可以访问构造函数的属性;
  • 这个对象可以访问构造函数原型上的属性;
  • 对象的**__proto__**属性指向了构造函数的原型;

由于new是关键字,我们只能去声明一个函数去实现new的功能,首先实现上面的三个特性,第一版代码如下:

附:对原型原型链不熟悉的可以先看理解Javascript的原型和原型链。

// construct: 构造函数
function newFunction() {
 var res = {};
 // 排除第一个构造函数参数
 var construct = Array.prototype.shift.call(arguments);
 res.__proto__ = construct.prototype;
 // 使用apply执行构造函数,将构造函数的属性挂载在res上面
 construct.apply(res, arguments);
 return res;
}

我们测试下:

function newFunction() {
 var res = {};
 var construct = Array.prototype.shift.call(arguments);
 res.__proto__ = construct.prototype;
 construct.apply(res, arguments);
 return res;
}
function Animal(name) {
  this.name = name;
}
Animal.prototype.sayName = function() {
  console.log("I'm " + this.name);
}
var cat = newFunction(Animal, 'Tom');
console.log(cat.name); // Tom
console.log(cat.__proto__ === Animal.prototype); // true
cat.sayName(); // I'm Tom

一切正常。new的特性实现已经80%,但new还有一个特性:

function Animal(name) {
  this.name = name;
  return {
    prop: 'test'
  };
}
var cat = new Animal('Tom');
console.log(cat.prop); // test
console.log(cat.name); // undefined
console.log(cat.__proto__ === Object.prototype); // true
console.log(cat.__proto__ === Animal.prototype); // false

如上,如果构造函数return了一个对象,那么new操作后返回的是构造函数return的对象。让我们来实现下这个特性,最终版代码如下:

// construct: 构造函数
function newFunction() {
 var res = {};
 // 排除第一个构造函数参数
 var construct = Array.prototype.shift.call(arguments);
 res.__proto__ = construct.prototype;
 // 使用apply执行构造函数,将构造函数的属性挂载在res上面
 var conRes = construct.apply(res, arguments);
 // 判断返回类型
 return conRes instanceof Object ? conRes : res;
}

测试下:

function Animal(name) {
  this.name = name;
 return {
  prop: 'test'
  };
}
var cat = newFunction(Animal, 'Tom');
console.log(cat.prop); // test
console.log(cat.name); // undefined
console.log(cat.__proto__ === Object.prototype); // true
console.log(cat.__proto__ === Animal.prototype); // false

以上代码就是我们最终对new操作符的模拟实现。我们再来看下官方对new的解释

引用MDN对new运算符的定义:

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。

new操作符会干下面这些事:

  • 创建一个空的简单JavaScript对象(即{});
  • 链接该对象(即设置该对象的构造函数)到另一个对象 ;
  • 将步骤1新创建的对象作为this的上下文 ;
  • 如果该函数没有返回对象,则返回this。

4条都已经实现。还有一个更好的实现,就是通过Object.create去创建一个空的对象:

// construct: 构造函数
function newFunction() {
 // 通过Object.create创建一个空对象;
 var res = Object.create(null);
 // 排除第一个构造函数参数
 var construct = Array.prototype.shift.call(arguments);
 res.__proto__ = construct.prototype;
 // 使用apply执行构造函数,将构造函数的属性挂载在res上面
 var conRes = construct.apply(res, arguments);
 // 判断返回类型
 return conRes instanceof Object ? conRes : res;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
线路分流自动跳转代码;希望对大家有用!
Dec 02 Javascript
菜鸟学习JavaScript小实验之函数引用
Nov 17 Javascript
javascript 保存文件到本地实现方法
Nov 29 Javascript
jQuery中animate()方法用法实例
Dec 24 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 图片库
Jan 09 Javascript
JS中的Replace方法使用经验分享
May 20 Javascript
浅析BootStrap中Modal(模态框)使用心得
Dec 24 Javascript
Bootstrap的popover(弹出框)在append后弹不出(失效)
Feb 27 Javascript
用最简单的方法判断JavaScript中this的指向(推荐)
Sep 04 Javascript
什么是Vue.js框架 为什么选择它?
Oct 17 Javascript
Electron-vue脚手架改造vue项目的方法
Oct 22 Javascript
vue flex 布局实现div均分自动换行的示例代码
Aug 05 Javascript
JS面向对象编程——ES6 中class的继承用法详解
Mar 03 #Javascript
JS面向对象编程实现的拖拽功能案例详解
Mar 03 #Javascript
序列化模块json代码实例详解
Mar 03 #Javascript
JS常用排序方法实例代码解析
Mar 03 #Javascript
JS面向对象编程实现的Tab选项卡案例详解
Mar 03 #Javascript
JS面向对象编程基础篇(三) 继承操作实例详解
Mar 03 #Javascript
小程序接入腾讯位置服务的详细流程
Mar 03 #Javascript
You might like
PHP 9 大缓存技术总结
2015/09/17 PHP
Laravel5.1框架路由分组用法实例分析
2020/01/04 PHP
thinkphp5实现微信扫码支付
2019/12/23 PHP
通过MSXML2自动获取QQ个人头像及在线情况(给初学者)
2007/01/22 Javascript
greybox——不开新窗口看新的网页
2007/02/20 Javascript
用jQuery简化JavaScript开发分析
2009/02/19 Javascript
Jquery替换已存在于element上的event的方法
2010/03/09 Javascript
jQuery遍历对象、数组、集合实例
2014/11/08 Javascript
解决JS请求服务器gbk文件乱码的问题
2015/10/16 Javascript
javascript编程异常处理实例小结
2015/11/30 Javascript
javascript 常用验证函数总结
2016/06/28 Javascript
浅谈Vue SPA 首屏加载优化实践
2017/12/15 Javascript
js脚本中执行java后台代码方法解析
2019/10/11 Javascript
JavaScript enum枚举类型定义及使用方法
2020/05/15 Javascript
小程序实现图片移动缩放效果
2020/05/26 Javascript
何时/使用 Vue3 render 函数的教程详解
2020/07/25 Javascript
vue element实现表格合并行数据
2020/11/30 Vue.js
py中的目录与文件判别代码
2008/07/16 Python
Python中针对函数处理的特殊方法
2014/03/06 Python
Python文件夹与文件的操作实现代码
2014/07/13 Python
Python模拟登陆实现代码
2017/06/14 Python
[原创]教女朋友学Python3(二)简单的输入输出及内置函数查看
2017/11/30 Python
对python文件读写的缓冲行为详解
2019/02/13 Python
python协程gevent案例 爬取斗鱼图片过程解析
2019/08/27 Python
Python使用socket模块实现简单tcp通信
2020/08/18 Python
Python如何爬取51cto数据并存入MySQL
2020/08/25 Python
Python descriptor(描述符)的实现
2020/11/15 Python
英国二手iPhone、音乐、电影和游戏商店:musicMagpie
2018/10/26 全球购物
财务人员个人求职信范文
2013/12/04 职场文书
《歌唱二小放牛郎》教学反思
2014/04/19 职场文书
大学优秀班主任事迹材料
2014/05/02 职场文书
晚自修旷课检讨书怎么写
2014/11/17 职场文书
2015年元旦标语大全
2014/12/09 职场文书
2015年销售助理工作总结
2015/05/11 职场文书
外出学习心得体会范文
2016/01/18 职场文书
2019学子的答谢词范本!
2019/07/05 职场文书