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


Posted in Javascript onNovember 20, 2015

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学习小结,之后每天还会继续更新,希望大家继续关注。

Javascript 相关文章推荐
JavaScript设置FieldSet展开与收缩
May 15 Javascript
javascript 构建一个xmlhttp对象池合理创建和使用xmlhttp对象
Jan 15 Javascript
JQuery弹出炫丽对话框的同时让背景变灰色
May 22 Javascript
JavaScript获得页面base标签中url的方法
Apr 03 Javascript
浅谈javascript的分号的使用
May 12 Javascript
Bootstrap禁用响应式布局的实现方法
Mar 09 Javascript
JavaScript实现微信红包算法及问题解决方法
Apr 26 Javascript
微信小程序实现长按删除图片的示例
May 18 Javascript
vue 之 css module的使用方法
Dec 04 Javascript
Vuex的各个模块封装的实现
Jun 05 Javascript
ES6 Symbol在对象中的作用实例分析
Jun 06 Javascript
原生js+css实现tab切换功能
Sep 17 Javascript
js鼠标点击图片切换效果实现代码
Nov 19 #Javascript
Bootstrap每天必学之简单入门
Nov 19 #Javascript
jquery实现横向图片轮播特效代码分享
Nov 19 #Javascript
Jquery 全选反选实例代码
Nov 19 #Javascript
Bootstrap每天必学之前端开发框架
Nov 19 #Javascript
Node.js中使用socket创建私聊和公聊聊天室
Nov 19 #Javascript
Jquery实现仿京东商城省市联动菜单
Nov 19 #Javascript
You might like
php中过滤非法字符的具体实现
2013/10/29 PHP
自编函数解决pathinfo()函数处理中文问题
2014/11/03 PHP
谈谈php对接芝麻信用踩的坑
2016/12/01 PHP
php探针不显示内存解决方法
2019/09/17 PHP
js读取配置文件自写
2014/02/11 Javascript
node.js中的fs.readdirSync方法使用说明
2014/12/17 Javascript
jQuery 实现侧边浮动导航菜单效果
2014/12/26 Javascript
jquery左右全屏大尺寸多图滑动效果代码分享
2015/08/28 Javascript
JS封装cookie操作函数实例(设置、读取、删除)
2015/11/17 Javascript
JavaScript数组方法总结分析
2016/05/06 Javascript
AngularJS中的包含详细介绍及实现示例
2016/07/28 Javascript
react-router中的属性详解
2017/06/01 Javascript
微信小程序通过保存图片分享到朋友圈功能
2018/05/24 Javascript
[00:56]2014DOTA2国际邀请赛 DK、iG 赛前探访
2014/07/10 DOTA
将Python代码嵌入C++程序进行编写的实例
2015/07/31 Python
python生成不重复随机数和对list乱序的解决方法
2018/04/09 Python
python使用BeautifulSoup与正则表达式爬取时光网不同地区top100电影并对比
2019/04/15 Python
python函数局部变量、全局变量、递归知识点总结
2019/11/15 Python
详解基于Jupyter notebooks采用sklearn库实现多元回归方程编程
2020/03/25 Python
Python之京东商品秒杀的实现示例
2021/01/06 Python
canvas版人体时钟的实现示例
2021/01/29 HTML / CSS
英国现代绅士品牌:Hackett
2017/12/17 全球购物
澳大利亚在线生活方式商店:Mytopia
2018/07/08 全球购物
阿里巴巴美国:Alibaba美国
2019/11/24 全球购物
合同专员岗位职责
2013/12/18 职场文书
2014两会优秀的心得体会范文
2014/03/17 职场文书
信电学院毕业生自荐书
2014/05/24 职场文书
2015年初中生自我评价范文
2015/03/03 职场文书
小马王观后感
2015/06/11 职场文书
教育读书笔记
2015/07/02 职场文书
小学运动会通讯稿
2015/07/18 职场文书
财务管理制度范本
2015/08/04 职场文书
《孙子兵法》:欲成大事者,需读懂这些致胜策略
2019/08/23 职场文书
Python实现随机生成迷宫并自动寻路
2021/06/13 Python
Spring Data JPA的Audit功能审计数据库的变更
2021/06/26 Java/Android
MySQL系列之四 SQL语法
2021/07/02 MySQL