this调用语句必须是构造函数中的第一个可执行语句_谈谈JavaScript中的函数构造式和new关键字...
您是否曾困惑于 Javascript 中的new关键字呢?是否曾想理解关于 function 和 constructor 的区别是什么呢?
大多数 Javascript 的新开发者不太想要使用new
关键字,因为这会让代码写的像是 Java 并且在使用上会造成一点混乱;在这篇文章我会尽量尝试着去理清这些东西,并解释它是如何运作的。
谈谈function constructor
constructor 翻为构造器但为了让您之后更好地理解,会直接使用 constructor;在 Javascript 中任何一个函数(function)都可以被当作 constructor;Javascript 并没有明确的区分两者,也就是说 function 可以被当作 constructor 或者当作一般函数调用。
而 constructor 的用法就是 function 搭配new
关键字:
function Person ( ) { this . firstName = 'Jay' ; this . lastName = 'Chou' ;
}var person = new Person ( ) ;
console . log ( person ) ;
接着我们把person呼叫出来看,会得到如下的结果,通过new它会帮我们建立一个对象,然后里面有Person这个function里面的内容,并且变成了属性名称和属性值:
进一步来看new 让这个过程发生了什么
当使用new
命令时,它后面的函数依次执行下面的4个步骤:
- 创建一个空对象,作为将要返回的对象实例。
- 将这个空对象的原型,指向构造函数的
prototype
属性。 - 将这个空对象赋值给函数内部的
this
关键字。 - 如果函数没有return其他对象,那么
new
表达式中的函数调用会自动返回这个新对象。
也就是说,当我们使用new这个关键字时,实际上会先有一个空的对象被建立。
接着People这个构造函数会被执行,这个空对象的原型,指向了People.prototype。
我们知道当函数执行的时候,在execution context中会有this被建立,而当我们使用new的时候,函数里面的this会被指定成刚刚所建立的那个空对象。
所以当执行People这个function,执行到this.firstName和this.lastName时,因为this现在指称的是那个空对象,所以实际上是在帮这个空对象赋予属性名称和属性值。
在这样的过程中,只要这个构造函数People 没有指定return为其他对象,它就会直接返回给我们这个新建立的对象。
接着让我们通过一段代码来更清楚的了解这个执行的过程:
function Person ( ) { this . firstName = 'Jay' ; this . lastName = 'Chou' ; console . log ( '这个函数有被执行' ) ;
}var person = new Person ( ) ;
console . log ( person ) ;
这时候在chrome 中呼叫出来的结果如下,说明了当我们使用new 在构造对象的时候People 这个function 确实有被执行:
通过new 会帮我们建立一个空的对象
现在我把我们上面的代码改成这样:
function Person ( ) { console . log ( this ) ;
}var person = new Person ( ) ;
// console.log(person);
这时候代码返回的结果如下,表示的确在执行这段代码的过程中帮我们建立了一个新的空对象:
函数的最后若return其他对象,则原新对象内容会被覆盖
现在,让我们把原本的代码稍微做如下修改:
function Person ( ) { this . firstName = 'Jay' ; this . lastName = 'Chou' ; return { "RETURN" : "原本this的内容就不会被返回" } ;
}var person = new Person ( ) ;
console . log ( person ) ;
构造函数的内部若return其他对象,new命令会返回return语句指定的对象,将原新对象内容覆盖掉;否则,就会不管return语句,返回this对象。返回的结果如下:
手写一个new实现
function create() {// 创建一个空的对象var obj = new Object(),// 获得构造函数,arguments中去除第一个参数Con = [].shift.call(arguments);// 链接到原型,obj 可以访问到构造函数原型中的属性obj.__proto__ = Con.prototype;// 绑定 this 实现继承,obj 可以访问到构造函数中的属性var ret = Con.apply(obj, arguments);// 优先返回构造函数返回的对象return ret instanceof Object ? ret : obj;
};
使用这个手写的new
function Person() {...}// 使用内置函数new
var person = new Person(...)// 使用手写的new,即create
var person = create(Person, ...)
代码原理解析:
- 用
new Object()
的方式新建了一个对象obj
- 取出第一个参数,就是我们要传入的构造函数。此外因为 shift 会修改原数组,所以
arguments
会被去除第一个参数 - 将
obj
的原型指向构造函数,这样obj
就可以访问到构造函数原型中的属性 - 使用
apply
,改变构造函数this
的指向到新建的对象,这样obj
就可以访问到构造函数中的属性 - 返回
obj
function constructor 的实际应用
由上面的方法,我们可以通过function的方式来建立一个新的对象,如果我们想要建立出同属性名称但不同属性值的对象内容,我们可以把对象的属性值变成参数,如此就能通过此function constructor建立出许多不同的对象:
function Person ( firstName , lastName ) { this . firstName = firstName ; this . lastName = lastName ;
}var person1 = new Person ( 'Jay' , 'chou' ) ;
console . log ( person1 ) ;
var person2 = new Person ( 'Jane' , 'chou' ) ;
console . log ( person2 ) ;
如此,我们就可以通过同一个构造函数建立出很多不同的对象:
此外,我们会把根据构造器(constructor)所建立出来的对象称作是实例(instance),这在之前的文章里也有提过。
注意!如果我们忘了加上new关键字
这里有一个地方我们需要非常留意,如果你在撰写代码的过程当中,忘记加上new这个关键字的话,比如:
function Person ( ) { this . firstName = 'Jay' ; this . lastName = 'Chou' ;
}var person = Person ( ) ;
console . log ( person ) ;
如此,因为JavaScript不知道你是要执行这个函数,还是要根据这个function去建立object,因次最后回传undefined的结果。
小结
- 其实构造函数(function constructor)就是普通的function,只是我们可以通过这个function 来建立对象。
- 通过在function 前面加上new 这个运算符,它会把函数中this 这个关键字建立成一个新的对象,然后如果你没有在该函数的内部指定返回出其它对象的话,它就会自动返回这个新的对象给你。
那又是如何通过function constructors 来设定我们的原型(prototype)呢?让我们在下一篇文章来谈吧!
如果觉得文章对你有些许帮助,欢迎在我的GitHub博客点赞和关注,感激不尽!
this调用语句必须是构造函数中的第一个可执行语句_谈谈JavaScript中的函数构造式和new关键字...相关推荐
- 5、this调用语句必须是构造函数中的第一个可执行语句_Java 构造函数
1.构造函数是用来干什么的 构造函数是用来初始化对象的成员属性的. 举个例子: public class MyClass {private String name;private int id;pub ...
- 5、this调用语句必须是构造函数中的第一个可执行语句_ES6中的Promise和Generator详解...
简介 ES6中除了上篇文章讲过的语法新特性和一些新的API之外,还有两个非常重要的新特性就是Promise和Generator,今天我们将会详细讲解一下这两个新特性. Promise 什么是Promi ...
- this调用语句必须是构造函数中的第一个可执行语句_详解-JavaScript 的 this 指向和绑定...
JavaScript 中的 new.bind.call.apply 实际这些都离不开 this,因此本文将着重讨论 this,在此过程中分别讲解其他相关知识点. 注意: 本文属于基础篇,请大神绕路.如 ...
- java结束程序是什么语句,在Java程序中,每条功能执行语句的最后都必须用结束。...
在Java程序中,每条功能执行语句的最后都必须用结束. 答: 分号 热继电器可以实现短路保护和过载保护 答:× 皮亚杰用表示通过作用或者操控物体和事件来发现其特点从而获取知识的人 答:建构者 品行包括 ...
- js模板字符串自定义类名_详解JavaScript ES6中的模板字符串
这篇文章主要介绍了详解JavaScript ES6中的模板字符串,JS的ES6版本带来诸多简洁化方面的重大改进,需要的朋友可以参考下 在 ES6 中引入了一种新的字符串字面量 - 模板字符串,除了使用 ...
- python调用cmd执行命令_详解python调用cmd命令三种方法
目前我使用到的python中执行cmd的方式有三种 使用os.system("cmd") 该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码, ...
- Java中final类是存放在哪_详解Java中的final关键字
1 修饰属性或者变量 无论属性是基本类型还是引用类型,作用都是变量里面存放的"值"不可变 经常和static关键字一起使用,作为常量 1 基本类型,变量放的是实实在在的值,如1,& ...
- python中 a or b 的值为_详解python中and和or的返回值
在Python 中,and 和 or 执行布尔逻辑演算,如你所期待的一样,但是它们并不返回布尔值:而是,返回它们实际进行比较的值之一. 一.and:>>> 'a' and 'b' ' ...
- 前端中unescape是什么意思_详解JavaScript中的Unescape()和String() 函数
JavaScript中的Unescape()和String() 函数详解,具体内容如下所示: 定义和用法 JavaScript unescape() 函数可对通过 escape() 编码的字符串进行解 ...
最新文章
- java实现https请求
- CKfinder2.0.2版本破解
- 排序 np_P问题、NP问题、NP完全问题和NP难问题理解
- 【AI白身境】只会用Python?g++,CMake和Makefile了解一下​​​​​​​
- debug工具_Jupyter官方神器:可视化 Debug 工具!
- 设置progressbar进度条颜色
- matlab判断能控和能观,实验三 利用Matlab分析能控性和能观性
- 无重复字符的最长子串php,LeetCode - 无重复字符的最长子串 - Golang
- 外链图片也有风险吗?
- Qt使用QPainter绘图的缩放问题
- python global 变量_python global全局变量 模块通信问题
- 苹果抛弃英特尔!TCL 怼格力 500 亿不够做芯片;高德地图上线叫车 | CSDN 极客头条...
- 修改fstab导致linux无法启动的解决
- java buffer类_Java ByteBuffer类
- ASP.NET版本不是1.1, 2.0的也一样
- 使用Python监控SNMP Trap并获取OSPF邻居状态
- 系统分析师-论文题目
- 深圳大学历届计算机文化节,第十二计算机文化节 | 与计算机应用能力大赛面对面...
- minecraft服务器stats文件夹,《我的世界》文件夹目录作用讲述
- vue中好用的视频插件推荐,video+canvas实现视频截图第一帧,ffmpeg实现视频截图第一帧
热门文章
- 【转】测试LibreOffice SDK 开发环境配置(Windows)
- Hibernate笔记——9.关联映射(下)
- 零基础Java学习之封装
- BZOJ4543/BZOJ3522 [POI2014]Hotel加强版(长链剖分)
- 转 layer的Icon样式以及一些常用的layer窗口使用
- 对不队—— Alpha冲刺
- 【转】Hadoop分布式集群搭建hadoop2.6+Ubuntu16.04
- 带你深度解析Maven
- 一种解决hadoop搭建出现的各种问题的简单粗暴的办法
- centos7下ip转发的配置