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 相关文章推荐
JQuery中$之选择器用法介绍
Apr 05 Javascript
Extjs EditorGridPanel中ComboBox列的显示问题
Jul 04 Javascript
深入理解JavaScript系列(11) 执行上下文(Execution Contexts)
Jan 15 Javascript
JS(JQuery)操作Array的相关方法介绍
Feb 11 Javascript
用JavaScript实现用一个DIV来包装文本元素节点
Sep 09 Javascript
js实现鼠标悬浮给图片加边框的方法
Jan 30 Javascript
JavaScript使用Max函数返回两个数字中较大数的方法
Apr 06 Javascript
js中对函数设置默认参数值的3种方法
Oct 23 Javascript
js图片跟随鼠标移动代码
Nov 26 Javascript
JavaScript与ActionScript3两者的同性与差异性
Sep 22 Javascript
React实现点击删除列表中对应项
Jan 10 Javascript
React-router中结合webpack实现按需加载实例
May 25 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版(1)
2006/10/09 PHP
ThinkPHP CURD方法之where方法详解
2014/06/18 PHP
Laravel使用RabbitMQ的方法示例
2019/06/18 PHP
php实现记事本案例
2020/10/20 PHP
JavaScript isPrototypeOf和hasOwnProperty使用区别
2010/03/04 Javascript
javaScript矢量图表库-gRaphael几行代码实现精美的条形图/饼图/点图/曲线图
2013/01/09 Javascript
jQuery创建DOM元素实例解析
2015/01/19 Javascript
JavaScript替换当前页面的方法
2015/04/03 Javascript
jQuery地图map悬停显示省市代码分享
2015/08/20 Javascript
javascript日期操作详解(脚本之家整理)
2015/09/05 Javascript
javascript同步服务器时间和同步倒计时小技巧
2015/09/24 Javascript
JavaScript获取当前运行脚本文件所在目录的方法
2016/02/03 Javascript
javascript js 操作数组 增删改查的简单实现
2016/06/20 Javascript
高效Web开发的10个jQuery代码片段
2016/07/22 Javascript
flag和jq on 的绑定多个对象和方法(必看)
2017/02/27 Javascript
vuex 项目结构目录及一些简单配置介绍
2018/04/08 Javascript
vue2.0项目实现路由跳转的方法详解
2018/06/21 Javascript
[44:21]Ti4 循环赛第四日 附加赛NEWBEE vs LGD
2014/07/13 DOTA
Python判断变量是否已经定义的方法
2014/08/18 Python
详解详解Python中writelines()方法的使用
2015/05/25 Python
python编写暴力破解zip文档程序的实例讲解
2018/04/24 Python
Python自定义装饰器原理与用法实例分析
2018/07/16 Python
python射线法判断一个点在图形区域内外
2019/06/28 Python
解决django 向mysql中写入中文字符出错的问题
2020/05/18 Python
python用Configobj模块读取配置文件
2020/09/26 Python
Python安装并操作redis实现流程详解
2020/10/13 Python
python在地图上画比例的实例详解
2020/11/13 Python
希尔顿酒店中国网站:Hilton中国
2017/03/11 全球购物
英国花园药房: The Garden Pharmacy
2017/12/28 全球购物
波兰电子产品购物网站:Vobis
2019/05/26 全球购物
美术毕业生求职信
2014/02/25 职场文书
无传销社区工作方案
2014/05/13 职场文书
环境日宣传活动总结
2014/07/09 职场文书
教师节倡议书2015
2015/04/27 职场文书
P站美图推荐——变身女主角特辑
2022/03/20 日漫
JDK8中String的intern()方法实例详细解读
2022/09/23 Java/Android