学习Javascript之模拟实现new

前言

本文1021字,阅读大约需要5分钟。

总括: 本文对new进行了一个简单介绍,然后使用一个函数模拟实现了new操作符做的事情。

  • 参考文档:new 运算符
  • 公众号:「前端进阶学习」,回复「666」,获取一揽子前端技术书籍

人生是没有毕业的学校。

正文

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

从上面的例子可以得出两点结论:

  1. new操作符实例化了一个对象;
  2. 这个对象可以访问构造函数的属性;
  3. 这个对象可以访问构造函数原型上的属性;
  4. 对象的**__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操作符会干下面这些事:

  1. 创建一个空的简单JavaScript对象(即{});
  2. 链接该对象(即设置该对象的构造函数)到另一个对象 ;
  3. 将步骤1新创建的对象作为this的上下文 ;
  4. 如果该函数没有返回对象,则返回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;
}

以上。



能力有限,水平一般,欢迎勘误,不胜感激。

订阅更多文章可关注公众号「前端进阶学习」,回复「666」,获取一揽子前端技术书籍

原文地址:https://www.cnblogs.com/jztan/p/12397423.html

时间: 2024-10-08 03:16:14

学习Javascript之模拟实现new的相关文章

学习Javascript之模拟实现bind

前言 本文1703字,阅读大约需要5分钟. 总括: 本文模拟实现了bind方法的更改this,传参和绑定函数作为构造函数调用时this失效的特性. 参考文档:Function.prototype.bind() 公众号:「前端进阶学习」,回复「666」,获取一揽子前端技术书籍 愿每次回忆,对生活都不感到负疚. 正文 bind和call,apply的作用类似,都是用来更改函数的this值的,不同的是,call和apply会直接把函数执行,但bind会返回一个函数,我们称之为绑定函数: functio

好程序员前端学习路线分享模拟JavaScript中面向对象技术

好程序员前端学习路线分享模拟JavaScript中面向对象技术,在C#和Java语言中,面向对象是以类的方式实现的,特别是继承这个特性,类的方式继承表现出了强大的功能,而且也易于学习.JavaScript不是纯的面向对象的语言,而是基于对象的语言,对象的继承是以原型函数的形式继承的,很多初学者刚开始接触的时候不太理解,但是JavaScript这种以原型函数的形式实现面向对象技术,不仅是可行的,而且还为面向对象技术提供了动态继承的功能,本文主要讨论了JavaScript的面向对象技术.?一.原型对

如何理解并学习javascript中的面向对象(OOP) [转]

如果你想让你的javascript代码变得更加优美,性能更加卓越.或者,你想像jQuery的作者一样,写出属于自己优秀的类库(哪怕是基于 jquery的插件).那么,你请务必要学习javascript面向对象,否则你无法更灵活的使用javascript这门语言. 什么事闭包?到底什么是原型?(知道闭包和原型的,就算得上是javascript的高手了.但真正能够理解,并且灵活运用的人并不多)到底该如何学习javascript中的面向对象呢?在javascript这么语言正如日中天,相信不少人正在为

一步步学习javascript基础篇(7):BOM和DOM

一.什么是BOM.什么是DOM BOM即浏览器对象模型,主要用了访问一些和网页无关的浏览器功能.如:window.location.navigator.screen.history等对象. DOM即文档对象模型,针对HTML(或XML)文档的API(应用程序编程接口).描绘的一个层次化的节点树,开发人员可以添加.修改和删除页面的某一部分. 二.细说BOM对象 1.window对象 window对象表示浏览器的一个实例,同时也是ECMAScript 规定的 Global 对象.(Global :所

一步步学习javascript基础篇(3):Object、Function等引用类型

我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂数据类型(即引用数据类型) Object类型 我们用的最多的引用类型就属object类型了,一般用来存储和传输数据是再好不过的.然,它的两种创建方式我们是否了解呢? 1.通过构造函数来创建 如: var obj = new Object(); 在js中的引用类型有个非常灵活的用法,可以动态的附加属性和赋值.

如何系统地学习JavaScript

在过去,JavaScript只是被用来做一些简单的网页效果,比如表单验证.浮动广告等,所以那时候JavaScript并没有受到重视.自从AJAX开始流行后,人们发现利用JavaScript可以给用户带来更好的体验,甚至利用这一优点开发了大型网页游戏,于是这门小语言被重视了起来.现在,很多公司会招专门的JavaScript工程师,通常JavaScript是WEB前端开发的必备技能.简单介绍了JavaScriptr的好处,并不代表大家就会去学习甚至把它学好,兴趣是很关键的,我认为兴趣是最好的老师,它

如何正确学习JavaScript

学习时长:6-8周学习前提:中学水平,无需编程经验 更新(2014-1-7) 在Reddit上创建了一个学习小组January 2014, “Learn JavaScript” Study Group on Reddit 目录 不要这样学习JavaScript 本课程资源 1-2周(简介,数据类型,表达式和操作符) 3~4周(对象,数组,函数,DOM,jQuery) JavaScript终极编辑器:WebStorm 第一个项目-动态问答应用 5-6周(正则表达式,Window对象,事件,jQue

学习JavaScript王者归来_02

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <html>     <head>         <title></title>         <script>             function ArrayList(array) {                 this._arr =

学习JavaScript中的异步Generator

本文和大家分享的主要是javascript中异步Generator相关内容,一起来看看吧,希望对大家学习javascript 有所帮助. 异步的generators和异步iteration已经到来 ! 这是错误的, 它们现在还在 阶段 3 ,这表示他们很有可能在JavaScript未来的一个版本中发布. 在他们发布之前,你可以通过 Babel 来在你的项目中使用还在阶段3的建议内容. 网站基本上还是一些分散运行的应用,因为任何在语言上的修改都会造成永久的影响,所以所有的未来的版本都需要向后兼容.