每天一篇javascript学习小结(面向对象编程)

1、面向对象的工厂方法

 function createPerson(name, age, job){
   var o = new Object();
   o.name = name;
   o.age = age;
   o.job = job;
   o.sayName = function(){
    alert(this.name);
   };
   return o;
  }

  var person1 = createPerson("Nicholas", 29, "Software Engineer");
  var person2 = createPerson("Greg", 27, "Doctor");

  person1.sayName(); //"Nicholas"
  person2.sayName(); //"Greg"

工厂模型的方法的缺点是会产生大量重复代码!

2、构造函数模式创建对象

 function Person(name, age, job){
   this.name = name;
   this.age = age;
   this.job = job;
   this.sayName = function(){
    alert(this.name);
   };
  }

  var person1 = new Person("Nicholas", 29, "Software Engineer");
  var person2 = new Person("Greg", 27, "Doctor");

  person1.sayName(); //"Nicholas"
  person2.sayName(); //"Greg"

  alert(person1 instanceof Object); //true
  alert(person1 instanceof Person); //true
  alert(person2 instanceof Object); //true
  alert(person2 instanceof Person); //true

  alert(person1.constructor == Person); //true
  alert(person2.constructor == Person); //true

  alert(person1.sayName == person2.sayName); //false  

使用new关键字创建对象会经历以下四个过程

  • 1、创建一个新对象
  • 2、将构造函数的作用域赋给一个新对象(因此this就指向了这个新对象)
  • 3、执行构造函数的方法(为这个新对象赋值)
  • 4、返回新对象

3、将构造函数当函数用

 function Person(name, age, job){
   this.name = name;
   this.age = age;
   this.job = job;
   this.sayName = function(){
    alert(this.name);
   };
  }

  var person = new Person("Nicholas", 29, "Software Engineer");
  person.sayName(); //"Nicholas"

  Person("Greg", 27, "Doctor"); //adds to window
  window.sayName(); //"Greg"

  var o = new Object();
  Person.call(o, "Kristen", 25, "Nurse");
  o.sayName(); //"Kristen"

构造函数当做函数使用就和普通的函数没有任何不同,它属于window对象下面添加的方法而已。由于构造函数创建的对象实际上是创建一个新对象,因此在本质上两者还是不一样的,还是分离的,他们的方法还是不一样的!

4、将共有的方法方法全局解决不一致的问题

 function Person(name, age, job){
   this.name = name;
   this.age = age;
   this.job = job;
   this.sayName = sayName;
  }

  function sayName(){
   alert(this.name);
  }

  var person1 = new Person("Nicholas", 29, "Software Engineer");
  var person2 = new Person("Greg", 27, "Doctor");

  person1.sayName(); //"Nicholas"
  person2.sayName(); //"Greg"

  alert(person1 instanceof Object); //true
  alert(person1 instanceof Person); //true
  alert(person2 instanceof Object); //true
  alert(person2 instanceof Person); //true

  alert(person1.constructor == Person); //true
  alert(person2.constructor == Person); //true

  alert(person1.sayName == person2.sayName); //true  

虽然上面的方法解决了一致的问题,但是定义的全局的方法本身属于window,那么局部和全局就没有分开!所以这个方法使用的并不多见!也不建议使用。

5、原型模式

我们创建的任何的一个函数都有一个原型对象,这个属性是一个指针,它指向一个对象,而这个对象的作用是可以有特定的类型的所有的实例共享的方法!

 function Person(){
  }

  Person.prototype.name = "Nicholas";
  Person.prototype.age = 29;
  Person.prototype.job = "Software Engineer";
  Person.prototype.sayName = function(){
   alert(this.name);
  };

  var person1 = new Person();
  person1.sayName(); //"Nicholas"

  var person2 = new Person();
  person2.sayName(); //"Nicholas"

  alert(person1.sayName == person2.sayName); //true

  alert(Person.prototype.isPrototypeOf(person1)); //true
  alert(Person.prototype.isPrototypeOf(person2)); //true

  //only works if Object.getPrototypeOf() is available
  if (Object.getPrototypeOf){
   alert(Object.getPrototypeOf(person1) == Person.prototype); //true
   alert(Object.getPrototypeOf(person1).name); //"Nicholas"
  }

理解原型

无论什么时候只要是创建了一个函数,就会创建一个原型属性,这个属性指向函数的原型对象。在默认的情况下,原型对象都会包含一个constructor(构造函数属性),这个属性包含一个指向prototype属性所在函数的指针!

属性读取的顺序

每当代码读取某个对象的属性时候,都会执行一次搜索,目标是具有给定名字的属性,搜索从对象的实例本身开始查找,如有则返回,没有则继续搜索该对象的原型链,直至搜索到原型链的最外层!

 function Person(){
  }

  Person.prototype.name = "Nicholas";
  Person.prototype.age = 29;
  Person.prototype.job = "Software Engineer";
  Person.prototype.sayName = function(){
   alert(this.name);
  };

  var person1 = new Person();
  var person2 = new Person();

  person1.name = "Greg";
  alert(person1.name); //"Greg" 来自实例
  alert(person2.name); //"Nicholas" 来自原型

如果删除了这个元素的实例属性

function Person(){
  }

  Person.prototype.name = "Nicholas";
  Person.prototype.age = 29;
  Person.prototype.job = "Software Engineer";
  Person.prototype.sayName = function(){
   alert(this.name);
  };

  var person1 = new Person();
  var person2 = new Person();

  person1.name = "Greg";
  alert(person1.name); //"Greg" ?from instance
  alert(person2.name); //"Nicholas" ?from prototype

  delete person1.name;
  alert(person1.name); //"Nicholas" - from the prototype

6、hasOwnProperty方法

这个方法可以检测一个属性是否存在于实例中,还是存在于原型中!hasOwnProperty是从Object继承来的,只要给定属性存在于对象实例中,才会返回true.

 function Person(){
    }

    Person.prototype.name = "Nicholas";
    Person.prototype.age = 29;
    Person.prototype.job = "Software Engineer";
    Person.prototype.sayName = function(){
      alert(this.name);
    };

    var person1 = new Person();
    var person2 = new Person();

    alert(person1.hasOwnProperty("name")); //false
    alert("name" in person1); //true

    person1.name = "Greg";
    alert(person1.name);  //"Greg" ?from instance
    alert(person1.hasOwnProperty("name")); //true
    alert("name" in person1); //true

    alert(person2.name);  //"Nicholas" ?from prototype
    alert(person2.hasOwnProperty("name")); //false
    alert("name" in person2); //true

    delete person1.name;
    alert(person1.name);  //"Nicholas" - from the prototype
    alert(person1.hasOwnProperty("name")); //false
    alert("name" in person1); //true

7、Object.keys() 可枚举属性方法

这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组

 function Person(){
    }

    Person.prototype.name = "Nicholas";
    Person.prototype.age = 29;
    Person.prototype.job = "Software Engineer";
    Person.prototype.sayName = function(){
      alert(this.name);
    };

    var keys = Object.keys(Person.prototype);
    alert(keys);  //"name,age,job,sayName"
如果想得到所有实例的属性,无论它是否可以枚举都可以使用这个方法来获取
 function Person(){
    }

    Person.prototype.name = "Nicholas";
    Person.prototype.age = 29;
    Person.prototype.job = "Software Engineer";
    Person.prototype.sayName = function(){
      alert(this.name);
    };

    var keys = Object.getOwnPropertyNames(Person.prototype);
    alert(keys);  //"constructor,name,age,job,sayName"

此方法高版本浏览器才支持

8、简单的原型写法

 function Person(){
    }

    Person.prototype = {
      name : "Nicholas",
      age : 29,
      job: "Software Engineer",
      sayName : function () {
        alert(this.name);
      }
    };

    var friend = new Person();

    alert(friend instanceof Object); //true
    alert(friend instanceof Person); //true
    alert(friend.constructor == Person); //false
    alert(friend.constructor == Object); //true

重写了原型就等于将默认的原型方法覆盖,那么同样的构造方法也会被重写,重写的构造方法指向了Object对象!而不是原来的对象Person

如果还是想指向之前的构造方法,可以显示的指定

 function Person(){
    }

    Person.prototype = {
      constructor : Person,
      name : "Nicholas",
      age : 29,
      job: "Software Engineer",
      sayName : function () {
        alert(this.name);
      }
    };

    var friend = new Person();

    alert(friend instanceof Object); //true
    alert(friend instanceof Person); //true
    alert(friend.constructor == Person); //true
    alert(friend.constructor == Object); //false

9、原型方法的动态添加

function Person(){
    }

    Person.prototype = {
      constructor: Person,
      name : "Nicholas",
      age : 29,
      job : "Software Engineer",
      sayName : function () {
        alert(this.name);
      }
    };

    var friend = new Person();

    Person.prototype.sayHi = function(){
      alert("hi");
    };

    friend.sayHi();  //"hi" ?works!

10、原生对象的原型方法

alert(typeof Array.prototype.sort);     //"function"
    alert(typeof String.prototype.substring);  //"function"

    String.prototype.startsWith = function (text) {//修改原生对象的原型方法
      return this.indexOf(text) == 0;
    };

    var msg = "Hello world!";
    alert(msg.startsWith("Hello"));  //true

11、组合使用构造函数和原型模式创建对象

//构造函数模式
function Person(name, age, job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.friends = ["Shelby", "Court"];
    }
    //原型模式
    Person.prototype = {
      constructor: Person,
      sayName : function () {
        alert(this.name);
      }
    };

    var person1 = new Person("Nicholas", 29, "Software Engineer");
    var person2 = new Person("Greg", 27, "Doctor");

    person1.friends.push("Van");

    alert(person1.friends);  //"Shelby,Court,Van"
    alert(person2.friends);  //"Shelby,Court"
    alert(person1.friends === person2.friends); //false
    alert(person1.sayName === person2.sayName); //true

12、动态原型模式

function Person(name, age, job){

      //properties
      this.name = name;
      this.age = age;
      this.job = job;

      //methods
      if (typeof this.sayName != "function"){

        Person.prototype.sayName = function(){
          alert(this.name);
        };

      }
    }

    var friend = new Person("Nicholas", 29, "Software Engineer");
    friend.sayName();

13、寄生构造函数模式

 function Person(name, age, job){
var o = new Object();//依赖全局对象初始化一个对象,然后再返回这个对象
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}

var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"

function SpecialArray(){ 

//create the array
var values = new Array();

//add the values
values.push.apply(values, arguments);

//assign the method
values.toPipedString = function(){
return this.join("|");
};

//return it
return values;
}

var colors = new SpecialArray("red", "blue", "green");
alert(colors.toPipedString()); //"red|blue|green"

alert(colors instanceof SpecialArray);

上诉方法有一点说明下,由于它是依赖外层对象来创建一个新对象,因此不能依赖 instanceof方法来确定属性和方法的来源!它实际上和构造函数的没有关系!

14、稳妥构造函数模式

 function Person(name, age, job){
      var o = new Object();
      o.sayName = function(){
        alert(name);
      };
      return o;
    }

    var friend = Person("Nicholas", 29, "Software Engineer");
    friend.sayName(); //"Nicholas"

此方法不依赖任何new this 关键符!如果要访问对象的方法和属性,只能通过对象已经定义好的方法来获取!

15、继承
javascript实现继承是通过原型链来实现的

function SuperType(){
      this.property = true;//定义一个属性
    }

    SuperType.prototype.getSuperValue = function(){//定义的原型方法
      return this.property;
    };

    function SubType(){
      this.subproperty = false;
    }

    //inherit from SuperType
    SubType.prototype = new SuperType();

    SubType.prototype.getSubValue = function (){
      return this.subproperty;
    };

    var instance = new SubType();
    alert(instance.getSuperValue());  //true

    alert(instance instanceof Object);   //true
    alert(instance instanceof SuperType);  //true
    alert(instance instanceof SubType);   //true

    alert(Object.prototype.isPrototypeOf(instance));  //true
    alert(SuperType.prototype.isPrototypeOf(instance)); //true
    alert(SubType.prototype.isPrototypeOf(instance));  //true
SubType继承SuperType的方法和属性,因此当instance可以直接调用SuperType的方法!
 function SuperType(){
      this.property = true;
    }

    SuperType.prototype.getSuperValue = function(){
      return this.property;
    };

    function SubType(){
      this.subproperty = false;
    }

    //inherit from SuperType
    SubType.prototype = new SuperType();

    //new method
    SubType.prototype.getSubValue = function (){
      return this.subproperty;
    };

    //override existing method
    SubType.prototype.getSuperValue = function (){
      return false;
    };

    var instance = new SubType();
    alert(instance.getSuperValue());  //false

上面的例子说明,重写的原型会覆盖之前继承的原型,最后返回的往往不是预期的效果

 function SuperType(){
      this.property = true;
    }

    SuperType.prototype.getSuperValue = function(){
      return this.property;
    };

    function SubType(){
      this.subproperty = false;
    }

    //inherit from SuperType
    SubType.prototype = new SuperType();

    //使用字面量添加的方法导致上面的方法失效了
    SubType.prototype = {
      getSubValue : function (){
        return this.subproperty;
      },

      someOtherMethod : function (){
        return false;
      }
    }; 

    var instance = new SubType();
    console.log(instance);
    alert(instance.getSuperValue());  //error!

下面的例子也说明重写原型带来的风险

 function SuperType(){
      this.colors = ["red", "blue", "green"];
    }

    function SubType(){
    }

    //inherit from SuperType
    SubType.prototype = new SuperType();

    var instance1 = new SubType();
    instance1.colors.push("black");
    alert(instance1.colors);  //"red,blue,green,black"

    var instance2 = new SubType();
    alert(instance2.colors);  //"red,blue,green,black"

原型共享导致两个不同的对象调用的同一个数据
16、借用构造函数来实现继承

 function SuperType(){
      this.colors = ["red", "blue", "green"];
    }

    function SubType(){
      //inherit from SuperType
      SuperType.call(this);
    }

    var instance1 = new SubType();
    instance1.colors.push("black");
    alert(instance1.colors);  //"red,blue,green,black"

    var instance2 = new SubType();
    alert(instance2.colors);  //"red,blue,green"

传递参数

 function SuperType(name){
      this.name = name;
    }

    function SubType(){
      //inherit from SuperType passing in an argument
      SuperType.call(this, "Nicholas");

      //instance property
      this.age = 29;
    }

    var instance = new SubType();
    alert(instance.name);  //"Nicholas";
    alert(instance.age);   //29

17、组合继承方式

function SuperType(name){
      this.name = name;
      this.colors = ["red", "blue", "green"];
    }

    SuperType.prototype.sayName = function(){
      alert(this.name);
    };

    function SubType(name, age){
      SuperType.call(this, name);

      this.age = age;
    }

18、原型继承

 function object(o){
      function F(){}
      F.prototype = o;
      return new F();
    }

    var person = {
      name: "Nicholas",
      friends: ["Shelby", "Court", "Van"]
    };

    var anotherPerson = object(person);
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");

19、寄生组合式继承

 function object(o){
      function F(){}
      F.prototype = o;
      return new F();
    }

    function inheritPrototype(subType, superType){
      var prototype = object(superType.prototype);  //create object
      prototype.constructor = subType;        //augment object
      subType.prototype = prototype;         //assign object
    }

    function SuperType(name){
      this.name = name;
      this.colors = ["red", "blue", "green"];
    }

    SuperType.prototype.sayName = function(){
      alert(this.name);
    };

    function SubType(name, age){
      SuperType.call(this, name);

      this.age = age;
    }

    inheritPrototype(SubType, SuperType);

    SubType.prototype.sayAge = function(){
      alert(this.age);
    };

    var instance1 = new SubType("Nicholas", 29);
    instance1.colors.push("black");
    alert(instance1.colors); //"red,blue,green,black"
    instance1.sayName();   //"Nicholas";
    instance1.sayAge();    //29

    var instance2 = new SubType("Greg", 27);
    alert(instance2.colors); //"red,blue,green"
    instance2.sayName();   //"Greg";
    instance2.sayAge();    //27

以上就是今天的javascript学习小结,之后每天还会继续更新,希望大家继续关注。

(0)

相关推荐

  • js面向对象之常见创建对象的几种方式(工厂模式、构造函数模式、原型模式)

    在上篇文章给大家介绍了javascript面向对象基础,本篇文章继续深入学习javascript面向对象,JS的语法非常灵活,简单的对象创建就有好几种不同的方法.这些过于灵活的地方有时候确实很让人迷惑,那么今天我们就来梳理一下JS中常用的创建对象的几种方法吧. 前言 虽然使用 Object构造函数 或者使用 对象字面量 可以很方便的用来创建一个对象,但这种方式有一个明显的缺点:使用一个接口创建多个对象会产生很多冗余的代码.因此为了解决这个问题,人们开始使用以下几种方式来常见对象. 工厂模式 该模

  • 简单分析javascript面向对象与原型

    本文主要内容参考来自JavaScript高级程序设计,面向对象与原型章节: 1.工厂模式 ECMAScript 可以通过工厂模式来创建对象: //工厂模式 function createObject(name, age) { var obj = new Object(); //创建对象 obj.name = name; //添加属性 obj.age = age; obj.run = function () { //添加方法 return this.name + this.age + '运行中..

  • 初步了解javascript面向对象

    前言 基于类的对象:我们都知道面向对象的语言中有一个明显的标志,就是都有类的概念,通过类这个类似模板的东西我们可以创建许多个具有相同的属性和方法的对象.然而在ECMAScript中并没有类的概念,自然它与基于类的语言中的对象也会有所不同. js中的对象: 无序 的属性的集合,属性可以包含基本值.对象.函数.即js中的对象是一组没有特定顺序的值,对象的每个属性或者方法都有一个自己的名字,而每个名字都与一个值相对应. 理解对象 创建对象的方式 1 创建一个对象的最简单的方式是创建一个Object实例

  • 详解JavaScript基于面向对象之继承实例

    javascript面向对象继承的简单实例: 作为一门面向对象的语言,继承自然是它的一大特性,尽管javascript的面向对象的实现机制和和c#和java这样典型的面向对象不同,但是继承的基本特点还是具有的,简单的说就是获得父级的方法和属性,下面是一段简单的实例,大家有兴趣可以分析一下: window.onload = function(){ function parent(age,name){ this.age = age; this.name = name; } parent.protot

  • JavaScript的面向对象编程基础

    重新认识面向对象 为了说明 JavaScript 是一门彻底的面向对象的语言,首先有必要从面向对象的概念着手 , 探讨一下面向对象中的几个概念: 一切事物皆对象 对象具有封装和继承特性 对象与对象之间使用消息通信,各自存在信息隐藏 以这三点做为依据,C++ 是半面向对象半面向过程语言,因为,虽然他实现了类的封装.继承和多态,但存在非对象性质的全局函数和变量.Java.C# 是完全的面向对象语言,它们通过类的形式组织函数和变量,使之不能脱离对象存在.但这里函数本身是一个过程,只是依附在某个类上.

  • Javascript简单实现面向对象编程继承实例代码

    本文讲述了Javascript简单实现面向对象编程继承实例代码.分享给大家供大家参考,具体如下: 面向对象的语言必须具备四个基本特征: 1.封装能力(即允许将基本数据类型的变量或函数放到一个类里,形成类的成员或方法) 2.聚合能力(即允许类里面再包含类,这样可以应付足够复杂的设计) 3.支持继承(父类可以派生出子类,子类拥有父母的属性或方法) 4.支持多态(允许同样的方法名,根据方法签名[即函数的参数]不同,有各自独立的处理方法) 这四个基本属性,javascript都可以支持,所以javasc

  • 详解JavaScript基于面向对象之创建对象(1)

    这一次我们深入的学习一下JavaScript面向对象技术,在学习之前,必要的说明一下一些面向对象的一些术语.这也是所有面对对象语言所拥有的共同点.有这样几个面向对象术语: 一.对象        ECMA-262把对象(object)定义为"属性的无序集合,每个属性存放一个原始值.对象或函数".严格来说,这意味着对象是无特定顺序的值的数组.尽管ECMAScript如此定义对象,但它更通用的定义是基于代码的名词(人.地点或事物)的表示. 二.类        每个对象都由类定义,可以把类

  • JavaScript面向对象之私有静态变量实例分析

    本文实例分析了JavaScript面向对象之私有静态变量.分享给大家供大家参考,具体如下: 大家知道,私有实例变量的原理是根据作用域. 私有实例变量是在Javascript的function内部用var关键字实现,只在function内部有效. 仿照这个,提出私有静态变量的解决方案: <script language="javascript" type="text/javascript"> var JSClass = (function() { var

  • 详解JavaScript基于面向对象之创建对象(2)

    接着上文<详解JavaScript基于面向对象之创建对象(1)>继续学习. 4.原型方式        我们创建的每个函数都有一个通过prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法.逻辑上可以这么理解:prototypt通过条用构造函数而创建的那个对象的原型对象.使用原型的好处就是可以让所有对象实例共享它所包含的属性和方法.也就是说,不必在构造函数中定义对象信息,而是直接将这些信息添加到原型中.        原型方式利用了对象的pr

  • js实现对ajax请求面向对象的封装

    AJAX 是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新. 在js中使用ajax请求一般包含三个步骤:               1.创建XMLHttp对象               2.发送请求:包括打开链接.发送请求               3.处理响应 在不使用任何的js框架的情况下,要想使用ajax,可能需要向下面一样进行代码的编写 <span style=&qu

  • 详解JavaScript基于面向对象之继承

    一.面相对象继承机制       这个实例使用UML很好的解释了继承机制.       说明继承机制最简单的方式是,利用一个经典的例子就是几何形状.实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边).圆是椭圆的一种,它只有一个焦点.三角形.矩形和五边形都是多边形的一种,具有不同数量的边.正方形是矩形的一种,所有的边等长.这就构成了一种完美的继承关系,很好的解释了面向对象的继承机制.        在这个例子中,形状是椭圆形和多边形的基类(通常我们也可以叫它父类,所有类都由

随机推荐