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的让textarea自适应高度的插件
Aug 03 Javascript
jQuery中 noConflict() 方法使用
Apr 25 Javascript
下拉列表选择项的选中在不同浏览器中的兼容性问题探讨
Sep 18 Javascript
jQuery获得内容和属性方法及示例
Dec 02 Javascript
Javascript自定义函数判断网站访问类型是PC还是移动终端
Jan 10 Javascript
JavaScript判断是否为数字的4种方法及效率比较
Apr 01 Javascript
js实现div在页面拖动效果
May 04 Javascript
利用select实现年月日三级联动的日期选择效果【推荐】
Dec 13 Javascript
jQuery弹出层插件popShow(改进版)用法示例
Jan 23 Javascript
JavaScript引用类型Function实例详解
Aug 09 Javascript
angular 实时监听input框value值的变化触发函数方法
Aug 31 Javascript
vue+AI智能机器人回复功能实现
Jul 16 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 curl 并发最佳实践代码分享
2012/09/05 PHP
php获取ip及网址的简单方法(必看)
2017/04/01 PHP
Javascript 函数中的参数使用分析
2010/03/27 Javascript
JQury slideToggle闪烁问题及解决办法
2011/07/05 Javascript
JS多物体 任意值 链式 缓冲运动
2012/08/10 Javascript
jQuery+ajax实现动态执行脚本的方法
2015/01/27 Javascript
jQuery Ajax中的事件详细介绍
2015/04/16 Javascript
详解JavaScript对Date对象的操作问题(生成一个倒数7天的数组)
2015/10/01 Javascript
JavaScript中iframe实现局部刷新的几种方法汇总
2016/01/06 Javascript
JS实现上下左右对称的九九乘法表
2016/02/22 Javascript
JavaScript 对象字面量讲解
2016/06/06 Javascript
js实现随机抽选效果、随机抽选红色球效果
2017/01/13 Javascript
JS异步文件上传(兼容IE8+)
2017/04/02 Javascript
基于$.ajax()方法从服务器获取json数据的几种方式总结
2018/01/31 Javascript
使用validate.js实现表单数据提交前的验证方法
2018/09/04 Javascript
vue中的mescroll搜索运用及各种填坑处理
2019/10/30 Javascript
解决antd Form 表单校验方法无响应的问题
2020/10/27 Javascript
对于Python异常处理慎用“except:pass”建议
2015/04/02 Python
Python3 导入上级目录中的模块实例
2019/02/16 Python
详解Selenium+PhantomJS+python简单实现爬虫的功能
2019/07/14 Python
pycharm不能运行.py文件的解决方法
2020/02/12 Python
Python开发之pip安装及使用方法详解
2020/02/21 Python
python实例化对象的具体方法
2020/06/17 Python
澳大利亚首屈一指的在线购物目的地:Kogan.com
2017/02/02 全球购物
英国拳击装备购物网站:RDX Sports
2018/01/23 全球购物
STUBHUB日本:购买和出售全球活动门票
2018/07/01 全球购物
网游商务专员求职信
2013/10/15 职场文书
工艺工程师岗位职责
2014/03/04 职场文书
财务总监管理职责范文
2014/03/09 职场文书
小班上学期评语
2014/05/05 职场文书
计算机科学与技术专业求职信
2014/09/03 职场文书
毕业实习证明(4篇)
2014/10/28 职场文书
工作经历证明范本
2015/06/15 职场文书
pytorch常用数据类型所占字节数对照表一览
2021/05/17 Python
python中opencv实现图片文本倾斜校正
2021/06/11 Python
vue实现登陆页面开发实践
2022/05/30 Vue.js