浅谈JavaScript对象与继承


Posted in Javascript onJuly 10, 2016

JavaScript是我在C语言之后接触的第二门编程语言,大一暑假的时候在图书馆找了一本中国人写的JavaScript程序设计来看。那个时候在编程方面几乎还是小白,再加上那本书根本没有提JavaScript的编程机制,又有一些误导性的话,一直以来对JavaScript有很深的误解,认为JavaScript只是一门在浏览器上运行的面向对象语言,值此文来写下JavaScript当中很具有迷惑性和容易误解的地方。当然限于作者水平有限,也没有什么开发经验,所以难免有疏漏之处,还望批评指正。

JavaScript的对象

对象是什么

JavaScript代码当中随处可见new关键字,很容易让人产生误解,认为JavaScript是Java一样是基于类继承的语言。但是事实并非如此,JavaScript当中并没有类,那JavaScript的对象不是类那又是什么呢?某种意义上说,JavaScript的对象就是Python当中的字典(哈希表),其实也就是类似这样的键值对:

me={
  "fisrtName" : "seek",
  "lastName" : "truth" ,
  "getName" : function(){
    return this.firstName+this.lastName; //this相当于指向这个对象的指针
  }
}

这是一个比较有误解性的地方,初次看到时候觉得有点无法理解,但仔细用一用还是觉得合理,我们既可以像Python一样用[]运算符来获取元素,也可以用.操作符来获取元素:

me.firstName // => seek
me["lastName"] //=> truth
me.getName() // => seektruth

new运算符

既然JavaScript当中是没有类的,那么new运算符又是在干什么呢?这是JavaScript设计的最让人误解的地方之一。JavaScript是一门函数式编程语言,JavaScript当中函数是一等公民,JavaScript当中函数也是对象,函数对象在被创建的时候会被添加调用属性,比较坑的是JavaScript函数有两种调用方式,一种是加了new关键字的调用,一种是没有new关键字的调用,前者会返回一个对象,后者会返回return语句当中的内容。考虑下面的一段函数:

function Obj(name){
  this.name=name;
  return name;
}

如果我们用new运算符来调用:

obj = new Obj("seektruth") //obj会是一个对象:{"name": "seektruth"}

如果我们直接调用:

obj = Obj("seektruth") //obj会是一个字符串:"seektruth"

确实设计的挺坑的,我们在调用的时候需要分清楚是否需要使用new,一般来说需要用new关键字来调用的函数会采用大写开头。

还有更坑的是如果返回的返回值是一个对象:

function Obj(name){
  this.name=name;
  return {};
}

这样无论我们是否用new运算符来调用都会返回return语句里的值:

new Obj("seektruth") //=> {}
Obj("seektruth") //=> {}

设计的是什么鬼......

对象继承

原型

前面已经说到过JavaScript当中是没有类的,那JavaScript又是怎么来实现继承的呢?答案是通过原型链。在JavaScript当中,每个对象都会有一个原型,在创建对象的时候,如果不加说明的话,对象继承的原型是Object.prototype,函数对象会继承Function.prototype(Function.prototype继承Object.prototype):

Object.prototype // => {}
Function.prototype // => [Function]

我们可以通过对象的__proto__熟悉来查看对象的原型:

a={}
a.__proto__ // => {}

JavaScript通过指定对象的原型来实现继承,指定对象的原型主要有三种方式,一是在构造函数当中指明原型,二是直接修改对象的__proto__属性,三是利用Object.create函数,下面我们依次来看一看

在构造函数当中指定原型

我们可以在构造函数当中指定对象的原型:

me={
  "firstName" : "seek",
  "lastName" : "truth" ,
  "getName" : function(){
    return this.firstName+this.lastName; //this相当于指向这个对象的指针
  }
}

function Obj(name){
  this.firstName = name;
  this.__proto__ = me; //指定原型为me对象
}

指定了原型之后,我们新建了对象之后就可以访问原型的属性:

obj = new Obj("foo"); // => { firstName: 'foo' }
obj.firstName // => foo
obj.lastName // => truth
obj.getName() // => "footruth"

当访问一个对象的时候,首先会尝试在改对象当中寻找该属性,如果没有就回到原型当中寻找,直到Object.prototype。如果我们在新的对象当中重写了原型当中的属性(方法),那么实际使用的时候我们新写的属性(方法)会覆盖掉原型当中的定义,这有点像基于类的语言的函数重载。

注意如果原型me对象的lastname属性有改变,因为obj对象是在原型当中寻找属性,那么这个obj对象的lastname属性也会改变:

me.lastName = "me"
obj.lastName // => "me"
obj.getName() // => "foome"

直接改变对象的原型

我们也可以直接指定(改变)对象的原型:

obj2 = {}
obj2.__proto__ = me
obj2.firstName // => seek
obj2.lastName // => "me"
obj2.getName() // => "seekme"

使用Object.create函数

尽管说前两种方法可以解决问题,但是这两种写法并不优雅,因为JavaScript并不是基于类的语言,第一写法很容易给人以误解,JavaScript语言精粹的作者Crockford认为new就不应该出现在JavaScript语言当中,而推荐使用Object.create函数来基于原型来创建对象。Object.create函数的用法很简单:

obj3 = Object.create(me) // 以me为原型创建新的对象
obj3.firstName // => seek
obj3.lastName // => "me"
obj3.getName() // => "seekme"

obj3 = Object.create(me) 与obj2 = {};obj2.proto = me是等价的,但是前一种写法更优雅也更易于理解。

总结

JavaScript作为一门基于原型的,函数式的编程语言在设计上有很多优雅与强大之处,但同时又有很多糟粕和坑,正式如此,JavaScript也是被误解最多语言。学习了JavaScript的对象继承机制,感觉自己的水平还是大有长进的。

以上这篇浅谈JavaScript对象与继承就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 判断Flash是否加载完成的代码
Apr 12 Javascript
jQuery autocomplate 自扩展插件、自动完成示例代码
Mar 28 Javascript
js中关于String对象的replace使用详解
May 24 Javascript
javascript结合html5 canvas实现(可调画笔颜色/粗细/橡皮)的涂鸦板
Apr 27 Javascript
JavaScript实现简单的二级导航菜单实例
Apr 15 Javascript
ES6所改良的javascript“缺陷”问题
Aug 23 Javascript
如何使用Vuex+Vue.js构建单页应用
Oct 27 Javascript
解决ie img标签内存泄漏的问题
Oct 13 Javascript
JS运动特效之同时运动实现方法分析
Jan 24 Javascript
基于Angular中ng-controller父子级嵌套的相关属性详解
Oct 08 Javascript
用vue写一个日历
Nov 02 Javascript
使用compose函数优化代码提高可读性及扩展性
Jun 16 Javascript
Bootstrap框架下下拉框select搜索功能
Mar 26 #Javascript
Bootstrap轮播插件中图片变形的终极解决方案 使用jqthumb.js
Jul 10 #Javascript
深入浅析JavaScript函数前面的加号和叹号
Jul 09 #Javascript
jQuery回到顶部的代码
Jul 09 #Javascript
jQuery 跨域访问解决原理案例详解
Jul 09 #Javascript
JavaScript跨域调用基于JSON的RESTful API
Jul 09 #Javascript
checkbox 选中一个另一个checkbox也会选中的实现代码
Jul 09 #Javascript
You might like
人大复印资料处理程序_查询篇
2006/10/09 PHP
用windows下编译过的eAccelerator for PHP 5.1.6实现php加速的使用方法
2007/09/30 PHP
屏蔽机器人从你的网站搜取email地址的php代码
2012/11/14 PHP
php获取网页标题和内容函数(不包含html标签)
2014/02/03 PHP
range 标准化之获取
2011/08/28 Javascript
基于jquery的滚动条滚动固定div(附演示下载)
2012/10/29 Javascript
JavaScript定义变量和变量优先级问题探讨
2014/10/11 Javascript
jquery实现拖拽调整Div大小
2015/01/30 Javascript
简介JavaScript中的setTime()方法的使用
2015/06/11 Javascript
简述JavaScript的正则表达式中test()方法的使用
2015/06/16 Javascript
Node.js的Express框架使用上手指南
2016/03/12 Javascript
js实现增加数字显示的环形进度条效果
2017/02/05 Javascript
JS检测是否可以访问公网服务器功能代码
2017/06/19 Javascript
关于JavaScript中的this指向问题总结篇
2017/07/23 Javascript
微信小程序movable view移动图片和双指缩放实例代码
2017/08/08 Javascript
js实现简易聊天对话框
2017/08/17 Javascript
jQuery中可见性过滤器简单用法示例
2018/03/31 jQuery
Vue开发实现吸顶效果的示例代码
2018/08/21 Javascript
JavaScript实现英语单词题库
2019/12/24 Javascript
浅要分析Python程序与C程序的结合使用
2015/04/07 Python
pandas 将list切分后存入DataFrame中的实例
2018/07/03 Python
python paramiko利用sftp上传目录到远程的实例
2019/01/03 Python
python-OpenCV 实现将数组转换成灰度图和彩图
2020/01/09 Python
详解Python中的路径问题
2020/09/02 Python
Room Mate Hotels美国:西班牙酒店品牌
2018/04/10 全球购物
The North Face北面美国官网:美国著名户外品牌
2018/09/15 全球购物
Rentalcars.com中国:世界上最大的在线汽车租赁服务
2019/08/22 全球购物
英国领先的独立酒精饮料零售商:DrinkSupermarket
2021/01/13 全球购物
应届生自荐书
2014/06/23 职场文书
竞选班干部演讲稿100字
2014/08/20 职场文书
招标授权委托书样本
2014/09/23 职场文书
教师自查自纠工作情况报告
2014/10/29 职场文书
2014社会治安综合治理工作总结
2014/12/04 职场文书
2019奶茶店创业计划书范本,值得你借鉴
2019/08/14 职场文书
Python机器学习算法之决策树算法的实现与优缺点
2021/05/13 Python
MySQL悲观锁与乐观锁的实现方案
2021/11/02 MySQL