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 相关文章推荐
动态加载js的几种方法
Oct 23 Javascript
Javascript String对象扩展HTML编码和解码的方法
Jun 02 Javascript
defer属性导致引用JQuery的页面报“浏览器无法打开网站xxx,操作被中止”错误的解决方法
Apr 27 Javascript
jquery 操作日期、星期、元素的追加的实现代码
Feb 07 Javascript
JavaScript给input的value赋值引发的关于基本类型值和引用类型值问题
Dec 07 Javascript
jquery实现下拉框功能效果【实例代码】
May 06 Javascript
jQuery实现的简单排序功能示例【冒泡排序】
Jan 13 Javascript
在一个页面实现两个zTree联动的方法
Dec 20 Javascript
浅谈JavaScript闭包
Apr 09 Javascript
微信小程序如何实现点击图片放大功能
Jan 21 Javascript
Vue如何提升首屏加载速度实例解析
Jun 25 Javascript
jQuery实现计算器功能
Oct 19 jQuery
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
《心理测量者3》剧场版动画预告
2020/03/02 日漫
在线短消息收发的程序,不用数据库
2006/10/09 PHP
php防攻击代码升级版
2010/12/29 PHP
一个不易被发现的PHP后门代码解析
2014/07/05 PHP
PHP基于Closure类创建匿名函数的方法详解
2017/08/17 PHP
讲两件事:1.this指针的用法小探. 2.ie的attachEvent和firefox的addEventListener在事件处理上的区别
2007/04/12 Javascript
jquery插件如何使用 jQuery操作Cookie插件使用介绍
2012/12/15 Javascript
一个级联菜单代码学习及removeClass与addClass的应用
2013/01/24 Javascript
通过点击jqgrid表格弹出需要的表格数据
2015/12/02 Javascript
jquery实现倒计时功能
2015/12/28 Javascript
基于JavaScript实现移除(删除)数组中指定元素
2016/01/04 Javascript
JS中如何实现复选框全选功能
2016/12/19 Javascript
Vue.js开发环境快速搭建教程
2017/03/17 Javascript
JavaScript编程设计模式之观察者模式(Observer Pattern)实例详解
2017/10/25 Javascript
详解Vue单元测试Karma+Mocha学习笔记
2018/01/31 Javascript
详解nodejs 配置文件处理方案
2019/01/02 NodeJs
微信小程序出现wx.getLocation再次授权问题的解决方法分析
2019/01/16 Javascript
微信小程序和H5页面间相互跳转代码实例
2019/09/19 Javascript
微信小程序canvas分享海报功能
2019/10/31 Javascript
vue引入静态js文件的方法
2020/06/20 Javascript
js+css实现扇形导航效果
2020/08/18 Javascript
Vue+penlayers实现多边形绘制及展示
2020/12/24 Vue.js
详解用python计算阶乘的几种方法
2019/08/14 Python
Python使用Opencv实现图像特征检测与匹配的方法
2019/10/30 Python
PyTorch 对应点相乘、矩阵相乘实例
2019/12/27 Python
Python 解决相对路径问题:"No such file or directory"
2020/06/05 Python
Python加速程序运行的方法
2020/07/29 Python
春节请假条
2014/04/11 职场文书
2015年学校财务工作总结
2015/05/19 职场文书
初中数学教学随笔
2015/08/15 职场文书
远程教育学习心得体会
2016/01/23 职场文书
适合毕业生创业的项目怎么找?
2019/08/08 职场文书
经典格言警句:没有热忱,世间便无进步
2019/11/13 职场文书
《家庭教育》读后感3篇
2019/12/18 职场文书
Android开发 使用文件储存的方式保存QQ密码
2022/04/24 Java/Android
HTML页面中使两个div并排显示的实现
2022/05/15 HTML / CSS