javascript必知必会之prototype
2016-07-12 18:40
507 查看
摘要
本系列博文主要谈一些在 javascript 使用中经常会混淆的高级应用,包括:prototype, closure, scope, this关键字. 对于一个需要提高自己javascript水平的程序员,这些都是必须要掌握的.
本节主要介绍prototype.
Contents
摘要
起由
prototype
结论
参考资料
本文的rst源码
起由
最近在做一个项目,里面大量地使用 javascript 作为页面的动态生成脚本,使用 json 与服务器进行通信. 在读之前遗留的代码时, 经常会弄不清楚, 作用域, this关键字在当前context下的指向等,于是便开始专门学习了
相关的知识,记录下来与大家分享.
下面的内容中会有一些代码,建议大家也去尝试修改和理解,这样更容易掌握. 点击 这儿 下载所涉及到的源码.
prototype
javascript 是一种 prototypebased programming 的语言, 而与我们通常的 class
based programming 有很大 的区别,我列举重要的几点如下:
函数是first class object, 也就是说函数与对象具有相同的语言地位
没有类,只有对象
函数也是一种对象,所谓的函数对象
对象是按 引用 来传递的
那么这种 prototype
based programming 的语言如何实现继承呢(OO的一大基本要素), 这也便是 prototype 的由来.
看下面的代码片断:
function foo(a, b, c) { return a*b*c; } alert(foo.length); alert(typeof foo.constructor); alert(typeof foo.call); alert(typeof foo.apply); alert(typeof foo.prototype);
对于上面的代码,用浏览器运行后你会发现:
length: 提供的是函数的参数个数
prototype: 是一个object
其它三个都是function
而对于任何一个函数的声明,它都将会具有上面所述的5个property(方法或者属性).
下面我们主要看下prototype.
// prototype function Person(name, gender) { this.name = name; this.gender = gender; this.whoAreYou = function(){//这个也是所谓的closure, 内部函数可以访问外部函数的变量 var res = "I'm " + this.name + " and I'm a " + this.gender +"."; return res; }; } // 那么在由Person创建的对象便具有了下面的几个属性 Person.prototype.age = 24; Person.prototype.getAge = function(){ return this.age; }; flag = true; if (flag) { var fun = new Person("Tower", "male"); alert(fun.name); alert(fun.gender); alert(fun.whoAreYou()); alert(fun.getAge()); } Person.prototype.salary = 10000; Person.prototype.getSalary = function(){ return this.name + " can earn about " + this.salary + "RMB each month." ; }; // 下面就是最神奇的地方, 我们改变了Person的prototype,而这个改变是在创建fun之后 // 而这个改变使得fun也具有了相同的属性和方法 // 继承的意味即此 if (flag) { alert(fun.getSalary()); alert(fun.constructor.prototype.age);//而这个相当于你直接调用 Person.prototype.age alert(Person.prototype.age); }
从上面的示例中我们可以发现,对于prototype的方法或者属性,我们可以 动态地 增加, 而由其创建的 对象自动会 继承 相关的方法和属性.
另外,每个对象都有一个 constructor 属性,用于指向创建其的函数对象,如上例中的 fun.constructor 指向的 就是 Person.
那么一个疑问就自然产生了, 函数对象中自身声明的方法和属性与prototype声明的对象有什么差别?
有下面几个差别:
自身声明的方法和属性是 静态的, 也就是说你在声明后,试图再去增加新的方法或者修改已有的方法,并不会 对由其创建的对象产生影响, 也即 继承 失败
而prototype可以动态地增加新的方法或者修改已有的方法, 从而是 动态的 ,一旦 父函数对象 声明了相关 的prototype属性,由其创建的对象会 自动继承 这些prototype的属性.
继续上面的例子:
flag = true; // 函数内部声明的方法是静态的,无法传递的 Person.school = "ISCAS"; Person.whoAreYou = function(){ return "zhutao"; };//动态更改声明期的方法,并不会影响由其创建的对象的方法, 即所谓的 静态 if (flag) { alert(Person.school); alert(fun.school);//输出的是 "undefined" alert(Person.whoAreYou()); //输出 zhutao alert(fun.whoAreYou()); // I'm Tower and I'm a male. } Person.prototype.getSalary = function(){ return "I can earn 1000000 USD"; }; if (flag) { alert(fun.getSalary());//已经继承了改变, 即所谓的 动态 }
既然有函数对象本身的属性, 也有prototype的属性, 那么是由其创建的对象是如何搜索相应的属性的呢?
基本是按照下面的流程和顺序来进行.
先去搜索函数对象本身的属性,如果找到立即执行
如果1没有找到,则会去搜索prototype属性,有2种结果,找到则直接执行,否则继续搜索 父对象 的 父对象 的prototype, 直至找到,或者到达 prototype chain 的结尾(结尾会是Object对象)
上面也回答如果函数对象本身的属性与prototype属性相同(重名)时的解决方式, 函数本身的对象 优先 .
再看一个多重prototype链的例子:
// 多重prototype链的例子 function Employee(name) { this.name = ""; this.dept = "general"; this.gender = "unknown"; } function WorkerBee() { this.projects = []; this.hasCar = false; } WorkerBee.prototype = new Employee; // 第一层prototype链 function Engineer() { this.dept = "engineer"; //覆盖了 "父对象" this.language = "javascript"; } Engineer.prototype = new WorkerBee; // 第二层prototype链 var jay = new Engineer("Jay"); if (flag) { alert(jay.dept); //engineer, 找到的是自己的属性 alert(jay.hasCar); // false, 搜索到的是自己上一层的属性 alert(jay.gender); // unknown, 搜索到的是自己上二层的属性 }
上面这个示例的对象关系如下:
![](http://farm3.static.flickr.com/2585/3933273719_ccab4562d2.jpg)
结论
javascript 的prototype给语言本身增加了很强的灵活性,但与 classbased programming 相比整个思维逻辑还是有很大的不同,所以需要更多地思考和揣摩.
而 javascript是披着c语言外衣的函数式语言 的理解自然也需要更多地思考.
下一节我会继续讨论下 javascript 的另一个重要而且比较容易弄错的知识 closure.
欢迎大家留言讨论.
相关文章推荐
- iis 不能访问json文件
- Yii2之使用javascript
- 关于使用imag.js出现的问题及解决方法(连载2)
- js 关键字 in 的使用方法
- 定时跳转
- js 中对象属性的特性
- js最新手机号码、身份证正则表达式
- js 中对象--对象结构(原型链基础解析)
- FastJSON、Gson和Jackson性能对比
- [JS实例] 跟随鼠标移动而发生视差动画的图片
- javascript类型系统——日期Date对象
- javascript中关于日期和时间的基础知识
- Jsp语法
- Javascript表单特效之十大常用原理性样例代码大总结
- jsp引擎是什么?是什么工作原理?
- extjs4.2.1 Ext.encode中文乱码问题
- JS进阶书籍
- JavaScript 事件代理绑定
- javascript 学习基础
- javascript介绍、变量、运算符-1