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 插件学习(三)
Aug 06 Javascript
jQuery实现单行文字间歇向上滚动源代码
Jun 02 Javascript
jquery点击缩略图切换视频播放特效代码分享
Sep 15 Javascript
基于javascript实现简单计算器功能
Jan 03 Javascript
总结jQuery插件开发中的一些要点
May 16 Javascript
javascript 玩转Date对象(实例讲解)
Jul 11 Javascript
angularjs数组判断是否含有某个元素的实例
Feb 27 Javascript
使用Nuxt.js改造已有项目的方法
Aug 07 Javascript
自己动手封装一个React Native多级联动
Sep 19 Javascript
解决iview多表头动态更改列元素发生的错误的方法
Nov 02 Javascript
详解keep-alive + vuex 让缓存的页面灵活起来
Apr 19 Javascript
webpack的tree shaking的实现方法
Sep 18 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 静态变量与自定义常量的使用方法
2010/01/26 PHP
thinkPHP+phpexcel实现excel报表输出功能示例
2017/06/06 PHP
jQuery 页面载入进度条实现代码
2009/02/08 Javascript
jQuery 插件 将this下的div轮番显示
2009/04/09 Javascript
文字溢出实现溢出的部分再放入一个新生成的div中具体代码
2013/05/17 Javascript
jquery入门必备的基本认识及实例(整理)
2013/06/24 Javascript
JQuery判断子iframe何时加载完成解决方案
2013/08/20 Javascript
javascript操纵OGNL标签示例代码
2014/06/16 Javascript
js判断手机和pc端选择不同执行事件的方法
2015/01/30 Javascript
js实现模拟银行卡账号输入显示效果
2015/11/18 Javascript
轻松5句话解决JavaScript的作用域
2016/07/15 Javascript
js本地图片预览实现代码
2016/10/09 Javascript
bootstrap datetimepicker实现秒钟选择下拉框
2017/01/05 Javascript
angular实现图片懒加载实例代码
2017/06/08 Javascript
bootstrap multiselect下拉列表功能
2017/08/22 Javascript
详解设置Webstorm 利用babel将ES6自动转码成ES5
2017/12/20 Javascript
Vue验证码60秒倒计时功能简单实例代码
2018/06/22 Javascript
原生JS实现的轮播图功能详解
2018/08/06 Javascript
js实现继承的方法及优缺点总结
2019/05/08 Javascript
vue element 关闭当前tab 跳转到上一路由操作
2020/07/22 Javascript
浅谈实现在线预览PDF的几种解决办法
2020/08/10 Javascript
vue data有值,但是页面{{}} 取不到值的解决
2020/11/09 Javascript
Python ValueError: invalid literal for int() with base 10 实用解决方法
2015/06/21 Python
python实现文本去重且不打乱原本顺序
2016/01/26 Python
python实现微信接口(itchat)详细介绍
2017/10/23 Python
django之session与分页(实例讲解)
2017/11/13 Python
详解python中Numpy的属性与创建矩阵
2018/09/10 Python
Python过滤txt文件内重复内容的方法
2018/10/21 Python
Python3 jupyter notebook 服务器搭建过程
2018/11/30 Python
Python GUI编程学习笔记之tkinter中messagebox、filedialog控件用法详解
2020/03/30 Python
多重CSS背景动画实现方法示例
2014/04/04 HTML / CSS
澳大利亚香水在线:Price Rite Mart
2017/12/28 全球购物
一加手机美国官方网站:OnePlus美国
2019/09/19 全球购物
初中生评语大全
2014/04/24 职场文书
我的中国梦演讲稿600字
2014/08/19 职场文书
2014坚持党风廉政建设思想汇报
2014/09/18 职场文书