没有对象?new一个!

2018-06-13 admin

我们都知道,使用new后可返回一个对象,通常用于实例化一个“类”。 用法:

function Student (name, age) {
    this.name = name;
    this.age = age;
}
Student.prototype.sayName = function() {
    console.log('I am '+ this.name);
}
const person =new Student('小明');
person.sayName();  // I am 小明

问题分析

首先我们分析一下,手动实现new需要什么。

  1. 创建一个函数,可返回一个新的对象
  2. 需要访问到Student构造函数里的属性
  3. 需要访问到Student.prototype中的属性和方法

具体步骤分析

一、参数传递

若要实现上面代码的相同效果,首先明确需要一个“类”的参数,以及其它参数(如name)。 js 的函数参数非常灵活,形参数量可不确定(使用...args),也可不给出。函数中有一个 与生俱来的arguments对象,具有length属性,但不是数组,所以不可使用数组方法。

arguments 简单分析

下述代码中的输出语句结果即为所传实参的集合:

{ ‘0’: [Function: Student], ‘1’: ‘小明’, ‘2’: 18 }

function objectFactory() {
    console.log(arguments);
}
const person = objectFactory(Student, '小明',18);

二、方法实现

1.得到 Student 类的构造函数

由前面 arguments 简单分析可知,arguments中的第一个参数即为Student的构造函数。上面说到,arguments 并非数组,那我们如何得到第一项呢?

两种方法:[].shift.call(arguments)Array.from(arguments)

var Constructor = [].shift.call(arguments);

2.创建一个新的对象

创建一个新的对象非常简单,如下:

const obj = new Object();

3.设置新对象的 __proto__ 属性

__proto__是对象的私有属性,指向构造该对象的构造函数的原型。所以此步须将新的对象的此属性指向 Constructor的原型。

obj.__proto__ = Constructor.prototype;

4.得到构造函数上的 this 属性

若要实例化一个“类”,则必须调用其构造函数,在执行构造函数时,其 this的值是动态的变化的,即为当前调用该函数的对象。

可是这里有个问题,若此时直接调用构造函数并传值

Constructor(arguments);

最终结果将为undefined

这是为什么呢?

原因是构造函数中的 this并没有指向当前的新对象,此时apply()方法就可完美解决这个问题(call()方法也可),具体的apply()的使用及apply()call()的异同可参照大神文章

结果:

function objectFactory(){
    var Constructor = [].shift.call(arguments);
    var obj = new Object();
    obj.__proto__ = Constructor.prototype;
    Constructor.apply(obj, arguments);
    return obj;
}

const person = objectFactory(Student, '小明', 18);
person.sayName();   // I am 小明

结束

对于手动实现new的学习,原型的概念更清晰了,在具体的实现过程中也学习到了shiftcallapply等方法的一些使用。收获颇丰。

原文链接:https://segmentfault.com/a/1190000015271766

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-33938.html

文章标题:没有对象?new一个!

相关文章
JavaScript包装对象
一切皆对象,即便是三种原始类型的值——数值、字符串、布尔值,在一定条件下,也会自动转为对象,也就是原始类型的“包装对象”。 看如下代码: var s='www.javascriptcn.com';//...
2015-11-11
freemarker判断对象是否为空的方法
FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。 freemarker中显示某对象使用${name}. 但如果nam...
2017-03-27
2015年Web:追求原有“框架”外的新功能
Web目前正在经历一场巨大的变化,ServiceWorkers、传感器访问、推送通知等方式将打破Web原有的框架。而在2015年我们可以利用这几种方式快速的改变自己的网站。在不断增多的Web功能中寻求最合适自己的功能。 Web最初的设想是一...
2015-11-12
Easyui Tree获取当前选择节点的所有顶级父节点
只支持四层目录结构,比较笨的一个方法 JS代码 var node = $('#tree').tree('getSelected'); //获取该节点所有父节点 ...
2017-03-17
JavaScript深入之类数组对象与
类数组对象 所谓的类数组对象: 拥有一个 length 属性和若干索引属性的对象 举个例子: var array = ['name', 'age', 'sex']; var ...
2017-05-27
js获取数组的最后一个元素
在js里面如何获取一个数组的最后一个元素呢?这里总结了两种方法,有需要的朋友可以看看。 (1)js内置pop方法 pop() 方法用于删除并返回数组的最后一个元素,注意这里在获取了数组的最后一个元素的同时也将原数组的最后一个元素给删除了。如...
2017-03-22
javascript原始值和对象引用实例分析
本文实例讲述了javascript原始值和对象引用的方法。分享给大家供大家参考。具体分析如下: 一句话来说:原始值是不可变的,而对象引用是可变的。 js中的原始值(undefined、null、布尔值、数字和字符串)与对象(包括数组和函数)...
2017-03-22
使用JavaScript制作一个简单的计数器的方法
设计思想 该方法的关键是Cookie技术和动态图像特性的综合运用。使用Cookie,可以在用户端的硬盘上记录用户的数据,下次访问此站点时,即可读取用户端硬盘的Cookie,直接得知来访者的身份和访问次数等有关信息。JavaScript中通过...
2017-03-27
浅析Node.js的Stream模块中的Readable对象
我一直都很不愿意扯 nodejs 的流,因为从第一次看到它我就觉得它的设计实在是太恶心了。但是没办法,Stream 规范尚未普及,而且确实有很多东西都依赖了 nodejs 的流来实现的,所以我也只能捏着鼻子硬着头皮来扯一扯这又臭又硬的 no...
2017-03-27
js面向对象之公有、私有、静态属性和方法详解
现下,javascript大行其道,对于网站开发人员来说,javascript是必需掌据的一门语言,但随着jquery等框架的流行和使用,许多人对于原生javascript缺乏深入的理解,习惯了函数式的编辑风格,对于闭包、原型总是说不清道不...
2017-03-22
回到顶部