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对象与继承就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊html" target="_blank">教程。
本文向大家介绍浅谈JavaScript面向对象--继承,包括了浅谈JavaScript面向对象--继承的使用技巧和注意事项,需要的朋友参考一下 一、继承的概念 子类共享父类的数据和方法的行为,就叫继承。 二、E55如何实现继承?探索JavaScript继承的本质 2.1构造函数之间的“复制粘贴” 第一条路是通过构造函数来继承,这可以理解为子类直接复制了父类构造函数的代码,然后按照一定的规矩“粘贴”
本文向大家介绍浅谈Javascript中的对象和继承,包括了浅谈Javascript中的对象和继承的使用技巧和注意事项,需要的朋友参考一下 Javascript是一门函数式编程语言,Javascript当中函数是核心,在Javascript中函数也是对象,函数对象在创建的时候会被添加属性和方法。 在Javascript中函数对象有两种调用方式,一种是new关键字的调用,另一种是没有new关键字的调
本文向大家介绍浅谈Javascript事件对象,包括了浅谈Javascript事件对象的使用技巧和注意事项,需要的朋友参考一下 如果是事件处理函数绑定的函数,浏览器会默认传递一个参数,而这个参数就是事件对象。 因为arguments[0]这样使用这个参数比较麻烦,所以我们可以传递一个参数evt来进行使用。 以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支
本文向大家介绍浅谈JavaScript的计时器对象,包括了浅谈JavaScript的计时器对象的使用技巧和注意事项,需要的朋友参考一下 1、JavaScript计时器,我们可以在设定的时间间隔之后来执行代码,而不是在函数被调用后立即执行。 计时器类型: 1)一次性计时器:仅在指定的延迟时间之后触发一次。 2)间隔性触发计时器:每隔一定的时间间隔就触发一次。 计时器方法: 1)setInterval
本文向大家介绍浅谈JavaScript对象的创建方式,包括了浅谈JavaScript对象的创建方式的使用技巧和注意事项,需要的朋友参考一下 通过Object构造函数或对象字面量创建对象时,使用同一个接口创建很多对象时,会产生大量的重复代码。为了简化,引入了工厂模式。 工厂模式 这种创建对象的方式大大简化了代码,然而也存在不足,那就是无法确定对象的类型。为了解决这个问题,出现下面这种模式。 构造函数
本文向大家介绍浅谈Javascript实现继承的方法,包括了浅谈Javascript实现继承的方法的使用技巧和注意事项,需要的朋友参考一下 S1:js中一切皆对象,想想如果要实现对父对象属性和方法的继承,最初我们会怎样子来实现呢,考虑到原型的概念,最初我是这样来实现继承的 从上面可以看到实现对Parent的继承主要是覆写了Son的prototype,这样便把Parent的属性和方法过给了Son的原