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 相关文章推荐
用javascript实现改变TEXTAREA滚动条和按钮的颜色,以及怎样让滚动条变得扁平
Apr 20 Javascript
jquery HotKeys轻松搞定键盘事件代码
Aug 30 Javascript
xml分页+ajax请求数据源+dom取结果实例代码
Oct 31 Javascript
显示js对象所有属性和方法的函数
Oct 16 Javascript
通过正则表达式实现表单验证是否为中文
Feb 18 Javascript
javascript比较两个日期相差天数的方法
Jul 23 Javascript
JavaScript纯色二维码变成彩色二维码
Jul 23 Javascript
各种选择框jQuery的选中方法(实例讲解)
Jun 27 jQuery
详解jquery选择器的原理
Aug 01 jQuery
Vue头像处理方案小结
Jul 26 Javascript
vue实现按需加载组件及异步组件功能
May 27 Javascript
新手简单了解vue
May 29 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.ini 中文版
2006/10/28 PHP
php+mysql分页代码详解
2008/03/27 PHP
PHP服务器页面间跳转实现方法
2012/08/02 PHP
使用php实现截取指定长度
2013/08/06 PHP
浅谈PHP正则表达式中修饰符/i, /is, /s, /isU
2014/10/21 PHP
php+flash+jQuery多图片上传源码分享
2020/07/27 PHP
PHP的Json中文处理解决方案
2016/09/29 PHP
php json相关函数用法示例
2017/03/28 PHP
jquery.idTabs 选项卡使用示例代码
2014/09/03 Javascript
用js读、写、删除Cookie代码续篇
2014/12/03 Javascript
js中的事件捕捉模型与冒泡模型实例分析
2015/01/10 Javascript
javascript判断css3动画结束 css3动画结束的回调函数
2015/03/10 Javascript
原生JavaScript实现异步多文件上传
2015/12/02 Javascript
JS数组合并push与concat区别分析
2015/12/17 Javascript
JS实现根据文件字节数返回文件大小的方法
2016/08/02 Javascript
JavaScript 函数的定义-调用、注意事项
2017/04/16 Javascript
bootstrap confirmation按钮提示组件使用详解
2017/08/22 Javascript
JS简单生成由字母数字组合随机字符串示例
2018/05/25 Javascript
js实现下拉框二级联动
2018/12/04 Javascript
原生JS实现随机点名项目的实例代码
2019/04/30 Javascript
Vue+Koa2+mongoose写一个像素绘板的实现方法
2019/09/10 Javascript
layui table 列宽百分比显示的实现方法
2019/09/28 Javascript
python动态网页批量爬取
2016/02/14 Python
Python3单行定义多个变量或赋值方法
2018/07/12 Python
Django xadmin开启搜索功能的实现
2019/11/15 Python
python设置代理和添加镜像源的方法
2020/02/14 Python
使用Python实现将多表分批次从数据库导出到Excel
2020/05/15 Python
Python 使用 PyQt5 开发的关机小工具分享
2020/07/16 Python
基于HTML5+Webkit实现树叶飘落动画
2017/12/28 HTML / CSS
在购买印度民族服饰:Soch
2020/09/15 全球购物
艺校音乐专业自我鉴定范文
2014/03/01 职场文书
六年级语文下册教学计划
2015/01/22 职场文书
2015年国际护士节演讲稿
2015/03/18 职场文书
管辖权异议上诉状
2015/05/23 职场文书
建议书的格式及范文
2015/09/14 职场文书
面试中老生常谈的MySQL问答集锦夯实基础
2022/03/13 MySQL