面向对象的javascript是这门语言被设计出来时就考虑的问题,熟悉OOP编程的概念后,学习不同的语言都会发现不同语言的实现是不同的,javascript的面向对象特性与其他具有面向对象特性的语言的实现的区别比较大,通过不断编程实践才能逐渐体会到面向对象的优点从而形成自己独特的javascript面向对象实现方式,这也是编写可重用代码的关键。

一、语言特性

对象(Object)是组成javascript 的基本单元,javascript中一切都是对象。其中引用(reference)、作用域(scope)、闭包(closure)和上下文(context)是其最重要的几个部分。

1、引用

引用是一个指向对象实际位置的指针,其中实际对象不能是引用,也就是引用指向的只能是具体的对象,而不能是另一个引用(不同于C语言中允许多级指针、perl语言中允许多层引用)。javascript里的结果沿着引用链一直上溯到原来那个对象,通过维护一系列对其他对象的引用构成了一个引用系统,提供了极大的灵活性。当实际对象改变之后,原来指向它的引用依然保持指向旧的对象。
  1. var obj = new Object();
  2. var objRef = obj;
  3. obj.oneProperty = 1;
  4. alert(obj.oneProperty == objRef.oneProperty);//显示true
  5. var items = new Array("1","2","3");
  6. var itemsRef = items;
  7. items.push("4");
  8. alert(items.length == itemsRef.length);//结果是true,因为Array对象将数组元素作为其属性对象保存
  9. items = new Array("one","two","three");
  10. alert(items != itemsRef); //结果true,已经是两个不同的对象了

2、函数重载和类型检查

重载在其他很多面向对象语言(C#、C++、java等)中都有实现,但是javascript没有直接支持,但是javascript的函数有一个arguments对象,本质是一个只读数组(只能读取信息,不能修改)。函数重载依赖判断传入参数数量和判断传入参数类型。前者使用arguments.length来获取。
参数类型判断:
  • 使用typeof操作符:返回一个字符串名称,表示变量内容的类型,当返回object时,自定义对象都是返回object,因此很难与其他对象区分。
  • 构造函数constructor属性:引用的是原来用来构造该对象的那个函数名。
而在区别如下表:
变量 typeof的值 变量.constructor
{an:"object"} "object" Object
["an","array"] "object" Array
function(){} "function" Function
"a string" "string" String
55 "number" Number
true "boolean" Boolean

3、作用域与闭包

javascript中作用于是由函数划分的,不是用块划分的。javascript运行时创建一个全局对象为其执行环境,为全局作用域,所有全局作用域中的变量都是window的属性。
闭包意味着内层的函数可以引用存在于包围它的函数内的变量,即使外层函数的执行已终止。想要保持访问能力的变量来自哪个函数,就必须在哪个函数内声明闭包。
首先可以使代码清晰,调用过程简洁。其次可以实现Curry化,就是通过把多个参数填充到函数体中,实现将函数转化为一个新的经过简化的接收更少参数的函数的技术。同时,由于闭包只能使用外层函数中变量的最终值而不是该变量创建时的值,最常见的就是for循环中的计数器,在闭包中调用函数时计数器是最后一次赋值,可以使用匿名函数解决。
  1. function delayAlert(msg,time){
  2. setTimeout(function(){
  3. alert(msg);
  4. }, time);
  5. }
  6. delayAlert("welcome", 2000);//调用代码清晰简洁
  7. function add(num){
  8. return function(toAdd){return num + toAdd};
  9. }
  10. var addFive = add(5);
  11. alert(addFive(4) == 9); //结果true,闭包实现函数的Curry化
  12. var obj = document.getElementById("main");
  13. var items = ["click", "keypress"];
  14. for(var i = 0; i < items.length; i++){
  15. (function(){
  16. var item = items[i];
  17. obj["on" + item] = function(){alert(item);};
  18. })();
  19. }
  20. //使用匿名函数激发出作用域,for循环中获得当前循环时的i值

4、上下文对象

javascript运行时创建全局执行环境,全局对象就是window的属性,上下文对象通过this变量体现。this指向当前对象所在的作用域的直系父对象,同时,提供了call和apply两个方法来改变函数执行的上下文。
  1. function changeColor(color){
  2. this.style.color = color;
  3. }
  4. changeColor.call(document.getElementById("main"), "black");

二、面向对象编程

1、对象及方法

对象是一系列属性的集合,与其他语言里的散列表结果类似。创建方式有三种
  • 使用new Object(),再单独添加属性和方法。仅单独为此对象添加属性方法,重新实例化的对象没有这些属性方法。
  • 使用{......}键值对创建。不能当做一个类来实例化新对象,只定义了一个对象,这就是实现单例设计模式的方法。当然从字面量实现创建新对象可以采用下面的方式:
     function object(o){
    function F(){};
    F.prototype = o;
    return new F();
    }
    var newObject = object(oldObject);
  • 使用构造函数创建,任何函数都可以被实例化为一个对象。
公共方法:对象的每个实例中都可以使用的公共方法,使用prototype属性,包含了一个可以作为所有新实例的基引用的对象。给原型添加属性的结果就是由改原型实例化的每个对象都会获得这些属性。
私有方法:在构造函数中单独申明的方法,理解为一个函数中的作用域下的私有变量,实例化的对象不能在外部访问。
特权方法:查看处理私有变量的同时允许用户已公共方法方式访问的方法。是在动态生成的,运行时才添加到对象中,不是在代码第一次编译生成的,比往对象的prototype上绑定方法的开销大,但是功能更大更灵活。
静态方法:仅为组织代码而使用的方法,不能在该对象的实例上下文中访问,只属于主对象本身的那个上下文中。
  1. function User(properties){
  2. for( var i in properties){ (function(which){
  3. var p = i;
  4. which["get" + p] = function(){return properties[p];};
  5. which["set" + p] = function(){properties[p] = val;};
  6. })(this);)
  7. }
  8. }
  9. //特权方法实例
  10. var user = new User({name:"Bob",age:44});
  11. alert(user.name == null); //没有name属性
  12. alert(user.getname() == "Bob");//动态获取属性
  13. user.setage(22);
  14. alert(user.getage() == 22);//动态获取

2、继承

  • 原型式继承:对象的构造函数可以从其他对象中继承方法,它创建出一个原型对象后,所有其他的新对象都可以基于这个原型对象来构建。
整个过程使用原型属性(prototype)来实现,这是每个函数都有的一个属性,适用于单继承而非多继承。可以减少内存开销,继承包含公共的属性或方法的对象。
  1. function Person(name){this.name = name;};
  2. Person.prototype.getName = function(){return this.name;};
  3. function User(name, password){this.name = name;
  4. this.password = password;};
  5. User.prototype = new Person();
  6. User.prototype.getPassword = function(){return this.password;};

其中User对象的原型prototype设置为一个Person对象,因此每当实例化User对象时,得到的每个User对象都会带有Person对象所有的方法,从而如同操作Person对象一样。这个技巧可以简化javascript的继承而编写一系列的包装函数。

  • 类式继承:带有方法的类就可以实例化为对象。
  1. //继承自单一函数。将新函数绑定到对象的prototype上
  2. Function.prototype.method = function(name, func){
  3. this.prototype[name] = func;
  4. return this;
  5. };
  6. Function.method('inherits', function(parent){var this.prototype = new parent(); return this;});
  7. //从单一父对象继承所有内容
  8. Function.method('swiss', function(parent){
  9. for (var i = 1; i < arguments.length; i++){
  10. var name = arguments[i];
  11. this.prototype[name] = parent.prototype[name];
  12. }
  13. return this;
  14. });

改进原型式继承的代码:

  1. function Person(name){this.name = name;};
  2. Person.method("getName", function(){}return name;);
  3. function User( name, password){
  4. this.name = name;
  5. this.password = password;
  6. };
  7. User.inherits( Person);
  8. User.method('getPassword', function(){return this.password;});
  9. User.method('getName', function(){return this.name;});

3、继承库

  • Base库,可以写出可读、有用好理解的面向对象javascript代码。
  • Prototype库,一个为了配合Ruby on Rails的web开发框架配合设计的javascript库,给核心javascript对象添加了一大堆的函数和属性。

作为现代javascript语言的基础,面向对象javascript集合了众多长处,编写干净的面向对象javascript代码能为开发应用程序带来极大帮助。

javascript进阶——面向对象特性的更多相关文章

  1. 从 prototype.js 深入学习 javascript 的面向对象特性

    从 prototype.js 深入学习 javascript 的面向对象特性 js是一门很强大的语言,灵活,方便. 目前我接触到的语言当中,从语法角度上讲,只有 Ruby 比它更爽. 不过我接触的动态 ...

  2. javascript 的面向对象特性参考

    最近在看用javascript+css实现rich client.javascript 也是一个蛮有意思的语言.特别是其面向对象的实现和其他“标准”的OO launguage有很大的不同.但是,都是动 ...

  3. Javascript 进阶 面向对象编程 继承的一个样例

    Javascript的难点就是面向对象编程,上一篇介绍了Javascript的两种继承方式:Javascript 进阶 继承.这篇使用一个样例来展示js怎样面向对象编程.以及怎样基于类实现继承. 1. ...

  4. Javascript 进阶 面向对象编程 继承的一个例子

    Javascript的难点就是面向对象编程,上一篇介绍了Javascript的两种继承方式:Javascript 进阶 继承,这篇使用一个例子来展示js如何面向对象编程,以及如何基于类实现继承. 1. ...

  5. JavaScript进阶面向对象ES6

    类和对象 对象:万物皆对象,对象是一个具体的事物,看得见摸得着的实物 对象是由属性和方法组成的: 属性:事物的特征,再对象中用属性来表示(常用名词) 方法:事物的行为,再对象中用方法来表示(常用动词) ...

  6. Javascript面向对象特性实现封装、继承、接口详细案例——进级高手篇

    Javascript面向对象特性实现(封装.继承.接口) Javascript作为弱类型语言,和Java.php等服务端脚本语言相比,拥有极强的灵活性.对于小型的web需求,在编写javascript ...

  7. Javascript面向对象特性实现封装、继承、接口详细案例

    Javascript面向对象特性实现(封装.继承.接口) Javascript作为弱类型语言,和Java.php等服务端脚本语言相比,拥有极强的灵活性.对于小型的web需求,在编写javascript ...

  8. JavaScript中面向对象的三大特性(一个菜鸟的不正经日常)

    经过几天的学习,把jQuery给啃会了,但是运用的还不算特别熟练,总感觉自己在JavaScript方面的基础十分欠缺,所以继续拾起JavaScript,开始更好的编程之旅~ 今天学的是JavaScri ...

  9. JavaScript进阶之路(一)初学者的开始

    一:写在前面的问题和话 一个javascript初学者的进阶之路! 背景:3年后端(ASP.NET)工作经验,javascript水平一般般,前端水平一般般.学习资料:犀牛书. 如有误导,或者错误的地 ...

随机推荐

  1. WPF-21:WPF实现仿安卓的图案密码键盘(改进)

    前面写了个简单的实现( http://blog.csdn.net/yysyangyangyangshan/article/details/9280439),不过效果不太好,各个点之间没有连接起来.这里 ...

  2. 删除已分配IP的静态IP地址池

    如果静态IP地址池已经分配了IP,则无法直接将其静态IP地址池删除,会提示出错:“已经有IP被分配,需要先将其回收,再删除” 如下: 查看IP地址池: Get-SCStaticIPAddressPoo ...

  3. HDU5100Chessboard(数论)

    HDU5100Chessboard(数论) 题目链接 题目大意:用k∗1的瓷砖区铺n∗n的矩形,问能铺上的最大的面积. 解题思路:这题没有直接得出结论:l = n%k, ans = max[(n^2 ...

  4. matlab两种不同模式的并行运算

    1.distributed job      distributed job是一种比較简单的并行任务.假定用户须要完毕一组作业.各个计算作业之间是独立的.并且相互之间不须要进行数据通信.这意味着各个作 ...

  5. 从 setNeedsLayout 说起

    本文从 setNeedsLayout 这个方法说起,分享与其相关的 UIKit 视图交互.使用场景等内容. UIKit 为 UIView 提供了这些方法来进行视图的更新与重绘: public func ...

  6. iOS之苹果和百度地图的使用

    iOS中使用较多的3款地图,google地图.百度地图.苹果自带地图(高德).其中苹果自带地图在中国使用的是高德的数据.苹果在iOS 6之后放弃了使用谷歌地图,而改用自家的地图.在国内使用的较多的就是 ...

  7. HTTP请求、响应报文格式

    HTTP请求报文格式: HTTP请求报文主要由请求行.请求头部.空行以及请求正文4部分组成 1,请求行由3部分组成,分别为:请求方式,URI(注意这里不是URL)以及协议版本组成,之间由空格分隔 请求 ...

  8. socket.io中emit和on的用法【转】

    socket.emit('action');表示发送了一个action命令,命令是字符串的,在另一端接收时,可以这么写: socket.on('action',function(){...});soc ...

  9. Spring-data-redis操作redis cluster

    Redis 3.X版本引入了集群的新特性,为了保证所开发系统的高可用性项目组决定引用Redis的集群特性.对于Redis数据访问的支持,目前主要有二种方式:一.以直接调用jedis来实现:二.使用sp ...

  10. sqlserver2008中如何用右键可视化的设置外键

    右键->设计 然后打表设计界面打开了然后右键点你要设置与其它表关联的列然后点关系,选择外键表与列然后点保存,就这样