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 相关文章推荐
裁剪字符串trim()自定义改进版
Apr 10 Javascript
jquery鼠标滑过提示title具体实现代码
Aug 06 Javascript
理解Javascript闭包
Nov 01 Javascript
jquery图片轮播特效代码分享
Apr 20 Javascript
JavaScript中使用Async实现异步控制
Aug 15 Javascript
Angular4表单验证代码详解
Sep 03 Javascript
微信小程序tabBar用法实例详解
Dec 04 Javascript
Vue下的国际化处理方法
Dec 18 Javascript
Vue组件和Route的生命周期实例详解
Feb 10 Javascript
ES6之模版字符串的具体使用
May 17 Javascript
JavaScript实现多态和继承的封装操作示例
Aug 20 Javascript
Vue中对iframe实现keep alive无刷新的方法
Jul 23 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防止网站被刷新的方法汇总
2014/12/01 PHP
PHP 读取大文件并显示的简单实例(推荐)
2016/08/12 PHP
阿里云PHP SMS短信服务验证码发送方法
2017/07/11 PHP
Track Image Loading效果代码分析
2007/08/13 Javascript
利用WebBrowser彻底解决Web打印问题(包括后台打印)
2009/06/22 Javascript
8款非常棒的响应式jQuery 幻灯片插件推荐
2012/02/02 Javascript
JS获取客户端IP地址、MAC和主机名的7个方法汇总
2014/07/21 Javascript
原生javascript实现图片滚动、延时加载功能
2015/01/12 Javascript
jquery实现横向图片轮播特效代码分享
2015/11/19 Javascript
Jquery ajax基础教程
2015/11/20 Javascript
jQuery实现微信长按识别二维码功能
2016/08/26 Javascript
Bootstrap基本插件学习笔记之Alert警告框(20)
2016/12/08 Javascript
Javascript中document.referrer隐藏来源的方法
2017/01/16 Javascript
vue2 自定义动态组件所遇到的问题
2017/06/08 Javascript
jQuery实现返回顶部按钮和scroll滚动功能[带动画效果]
2017/07/05 jQuery
vue如何使用 Slot 分发内容实例详解
2017/09/05 Javascript
Vue的移动端多图上传插件vue-easy-uploader的示例代码
2017/11/27 Javascript
Router解决跨模块下的页面跳转示例
2018/01/11 Javascript
JS双向链表实现与使用方法示例(增加一个previous属性实现)
2019/01/31 Javascript
JS中的算法与数据结构之常见排序(Sort)算法详解
2019/08/16 Javascript
详解Django框架中的视图级缓存
2015/07/23 Python
深入解析Python编程中JSON模块的使用
2015/10/15 Python
python实现校园网自动登录的示例讲解
2018/04/22 Python
Python解决pip install时出现的Could not fetch URL问题
2019/08/01 Python
python爬虫 基于requests模块发起ajax的get请求实现解析
2019/08/20 Python
python中的线程threading.Thread()使用详解
2019/12/17 Python
python实现跨excel sheet复制代码实例
2020/03/03 Python
解决python执行较大excel文件openpyxl慢问题
2020/05/15 Python
Python 实现3种回归模型(Linear Regression,Lasso,Ridge)的示例
2020/10/15 Python
详解Pymongo常用查询方法总结
2021/01/29 Python
公司捐款倡议书
2014/05/14 职场文书
单位工作证明
2014/10/07 职场文书
预备党员自我批评思想汇报
2014/10/10 职场文书
医院护士工作检讨书
2014/10/26 职场文书
使用GO语言实现Mysql数据库CURD的简单示例
2021/08/07 Golang
JavaScript实现简单的音乐播放器
2022/08/14 Javascript