JS面向对象编程基础篇(一) 对象和构造函数实例详解


Posted in Javascript onMarch 03, 2020

本文实例讲述了JS面向对象编程对象和构造函数。分享给大家供大家参考,具体如下:

面向对象编程(Object Oriented Programming,缩写为 OOP)是目前主流的编程范式。它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。每一个对象都是功能中心,具有明确分工,可以完成接受信息、处理数据、发出信息等任务。对象可以复用,通过继承机制还可以定制。因此,面向对象编程具有灵活、代码可复用、高度模块化等特点,容易维护和开发,比起由一系列函数或指令组成的传统的过程式编程(procedural programming),更适合多人合作的大型软件项目。

1.对象(object)

(1)对象是单个实物的抽象。

一本书、一辆汽车、一个人都可以是对象,一个数据库、一张网页、一个与远程服务器的连接也可以是对象。当实物被抽象成对象,实物之间的关系就变成了对象之间的关系,从而就可以模拟现实情况,针对对象进行编程。

(2)对象是一个容器,封装了属性(property)和方法(method)。

属性是对象的状态,方法是对象的行为(完成某种任务)。比如,我们可以把动物抽象为animal对象,使用“属性”记录具体是那一种动物,使用“方法”表示动物的某种行为(奔跑、捕猎、休息等等)。

2.构造函数

面向对象编程的第一步,就是要生成对象。前面说过,对象是单个实物的抽象。通常需要一个模板,表示某一类实物的共同特征,然后对象根据这个模板生成。JavaScript 语言使用构造函数(constructor)作为对象的模板。所谓”构造函数”,就是专门用来生成实例对象的函数。它就是对象的模板,描述实例对象的基本结构。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。

构造函数就是一个普通的函数,但是有自己的特征和用法。

var Vehicle = function () {
 this.price = 1000;
};

上面代码中,Vehicle就是构造函数。为了与普通函数区别,构造函数名字的第一个字母通常大写。

构造函数的特点有两个:

  • 函数体内部使用了this关键字,代表了所要生成的对象实例。
  • 生成对象的时候,必须使用new命令。

下面先介绍new命令:

3.new 命令

new命令的作用,就是执行构造函数,返回一个实例对象。

var Vehicle = function () {
 this.price = 1000;
};
 
var v = new Vehicle();
v.price // 1000

上面代码通过new命令,让构造函数Vehicle生成一个实例对象,保存在变量v中。这个新生成的实例对象,从构造函数Vehicle得到了price属性。new命令执行时,构造函数内部的this,就代表了新生成的实例对象,this.price表示实例对象有一个price属性,值是1000。

使用new命令时,根据需要,构造函数也可以接受参数。

var Vehicle = function (p) {
 this.price = p;
};
 
var v = new Vehicle(500);

new命令本身就可以执行构造函数,所以后面的构造函数可以带括号,也可以不带括号。下面两行代码是等价的,但是为了表示这里是函数调用,推荐使用括号。

// 推荐的写法
var v = new Vehicle();
// 不推荐的写法
var v = new Vehicle;

一个很自然的问题是,如果忘了使用new命令,直接调用构造函数会发生什么事?

这种情况下,构造函数就变成了普通函数,并不会生成实例对象。而且由于后面会说到的原因,this这时代表全局对象,将造成一些意想不到的结果。

var Vehicle = function (){
 this.price = 1000;//this指向window
};
 
var v = Vehicle();
v // undefined
price // 1000

上面代码中,调用Vehicle构造函数时,忘了加上new命令。结果,变量v变成了undefined,而price属性变成了全局变量。因此,应该非常小心,避免不使用new命令、直接调用构造函数。

为了保证构造函数必须与new命令一起使用,一个解决办法是使用严格模式。这样的话,一旦忘了使用new命令,直接调用构造函数就会报错。

'use strict';//由于严格模式中,函数内部的this不能指向全局对象,默认等于undefined
var Vehicle = function (){ 
	this.price = 1000;//因为使用严格模式,this为undefined
};
 
var v = Vehicle();
function Fubar(foo, bar){
 'use strict';
 debugger
 this._foo = foo;
 this._bar = bar;
}
Fubar()

上面代码的Fubar为构造函数,use strict命令保证了该函数在严格模式下运行。由于严格模式中,函数内部的this不能指向全局对象,默认等于undefined,导致不加new调用会报错(JavaScript 不允许对undefined添加属性)。

new 命令的原理

使用new命令时,它后面的函数依次执行下面的步骤。

  1. 创建一个空对象,作为将要返回的对象实例。
  2. 将这个空对象的原型,指向构造函数的prototype属性。
  3. 将这个空对象赋值给函数内部的this关键字。
  4. 开始执行构造函数内部的代码

也就是说,构造函数内部,this指的是一个新生成的空对象,所有针对this的操作,都会发生在这个空对象上。构造函数之所以叫“构造函数”,就是说这个函数的目的,就是操作一个空对象(即this对象),将其“构造”为需要的样子。

如果构造函数内部有return语句,而且return后面跟着一个对象,new命令会返回return语句指定的对象;否则,就会不管return语句,返回this对象。

var Vehicle = function () {
 this.price = 1000;
 return 1000;
};
 
(new Vehicle()) === 1000
// false

上面代码中,构造函数Vehiclereturn语句返回一个数值。这时,new命令就会忽略这个return语句,返回“构造”后的this对象。

但是,如果return语句返回的是一个跟this无关的新对象,new命令会返回这个新对象,而不是this对象。这一点需要特别引起注意。

var Vehicle = function (){
 this.price = 1000;
 return { price: 2000 };
};
 
(new Vehicle()).price
// 2000

上面代码中,构造函数Vehiclereturn语句,返回的是一个新对象。new命令会返回这个对象,而不是this对象。

另一方面,如果对普通函数(内部没有this关键字的函数)使用new命令,则会返回一个空对象。

function getMessage() {
 return 'this is a message';
}
 
var msg = new getMessage();
 
msg // {}
typeof msg // "object"

上面代码中,getMessage是一个普通函数,返回一个字符串。对它使用new命令,会得到一个空对象。这是因为new命令总是返回一个对象,要么是实例对象,要么是return语句指定的对象。本例中,return语句返回的是字符串,所以new命令就忽略了该语句。

 

new.target

函数内部可以使用new.target属性。如果当前函数是new命令调用,new.target指向当前函数,否则为undefined

function f() {
 console.log(new.target === f);
}
 
f() // false
new f() // true

使用这个属性,可以判断函数调用的时候,是否使用new命令。

function f() {
 if (!new.target) {
  throw new Error('请使用 new 命令调用!');
 }
 // ...
}
 
f() // Uncaught Error: 请使用 new 命令调用!

上面代码中,构造函数f调用时,没有使用new命令,就抛出一个错误。

Object.create() 创建实例对象

构造函数作为模板,可以生成实例对象。但是,有时拿不到构造函数,只能拿到一个现有的对象。我们希望以这个现有的对象作为模板,生成新的实例对象,这时就可以使用Object.create()方法。

var person1 = {
 name: '张三',
 age: 38,
 greeting: function() {
  console.log('Hi! I\'m ' + this.name + '.');
 }
};
 
var person2 = Object.create(person1);
 
person2.name // 张三
person2.greeting() // Hi! I'm 张三.

上面代码中,对象person1person2的模板,后者继承了前者的属性和方法。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
根据分辩率调用不同的CSS.
Jan 08 Javascript
jQuery学习笔记 更改jQuery对象
Sep 19 Javascript
Eval and new funciton not the same thing
Dec 27 Javascript
GRID拖拽行的实例代码
Jul 18 Javascript
jquery与prototype框架的详细对比
Nov 21 Javascript
清除div下面的所有标签的方法
Feb 17 Javascript
node.js中的forEach()是同步还是异步呢
Jan 29 Javascript
JavaScript实现表格点击排序的方法
May 11 Javascript
求js数组的最大值和最小值的四种方法
Mar 03 Javascript
vue图片加载与显示默认图片实例代码
Mar 16 Javascript
Vue-resource拦截器判断token失效跳转的实例
Oct 27 Javascript
详解vue使用$http服务端收不到参数
Apr 19 Javascript
vue中改变滚动条样式的方法
Mar 03 #Javascript
vue倒计时刷新页面不会从头开始的解决方法
Mar 03 #Javascript
vuex(vue状态管理)的特殊应用案例分享
Mar 03 #Javascript
使用vue打包进行云服务器上传的问题
Mar 02 #Javascript
微信小程序scroll-view的滚动条设置实现
Mar 02 #Javascript
JS如何生成随机验证码
Mar 02 #Javascript
js实现烟花特效
Mar 02 #Javascript
You might like
PHP 截取字符串 分别适合GB2312和UTF8编码情况
2009/02/12 PHP
php实现字符串首字母大写和单词首字母大写的方法
2015/03/14 PHP
php模拟post上传图片实现代码
2016/06/24 PHP
JavaScript面向对象之体会[总结]
2008/11/13 Javascript
跨浏览器的事件对象介绍
2012/06/27 Javascript
用nodejs写的一个简单项目打包工具
2013/05/11 NodeJs
JQuery加载图片自适应固定大小的DIV
2013/09/12 Javascript
js阻止默认事件与js阻止事件冒泡示例分享 js阻止冒泡事件
2014/01/27 Javascript
详解JavaScript语言的基本语法要求
2015/11/20 Javascript
通过隐藏iframe实现无刷新上传文件操作
2016/03/16 Javascript
vuejs2.0实现分页组件使用$emit进行事件监听数据传递的方法
2017/02/22 Javascript
vue+ElementUI实现订单页动态添加产品数据效果实例代码
2017/07/13 Javascript
node跨域转发 express+http-proxy-middleware的使用
2018/05/31 Javascript
Vue不能检测到Object/Array更新的情况的解决
2018/06/26 Javascript
python发送邮件功能实现代码
2016/07/15 Python
使用Python脚本和ADB命令实现卸载App
2017/02/10 Python
PyCharm第一次安装及使用教程
2020/01/08 Python
python 使用递归实现打印一个数字的每一位示例
2020/02/27 Python
python pandas利用fillna方法实现部分自动填充功能
2020/03/16 Python
Python常用编译器原理及特点解析
2020/03/23 Python
Python调用OpenCV实现图像平滑代码实例
2020/06/19 Python
Python turtle库的画笔控制说明
2020/06/28 Python
Python 实现将某一列设置为str类型
2020/07/14 Python
python3中数组逆序输出方法
2020/12/01 Python
python+selenium爬取微博热搜存入Mysql的实现方法
2021/01/27 Python
Baby Tulai澳大利亚:美国婴儿背带品牌
2018/10/15 全球购物
如何强制垃圾回收
2015/10/06 面试题
计算s=f(f(-1.4))的值
2014/05/06 面试题
元宵晚会主持词
2014/03/25 职场文书
教师党员自我剖析材料
2014/09/29 职场文书
2014年采购部工作总结
2014/11/20 职场文书
4S店销售内勤岗位职责
2015/04/13 职场文书
升学宴祝酒词
2015/08/11 职场文书
python爬虫之爬取笔趣阁小说
2021/04/22 Python
2021好看的国漫排行榜前十名 《完美世界》上榜,《元龙》排名第一
2022/03/18 国漫
详细介绍python操作RabbitMq
2022/04/12 Python