您的位置:首页 > Web前端 > JavaScript

js面向对象之构造函数、封装与继承

2017-04-29 20:25 369 查看
面向对象:是一种处理问题的思路,是对传统面向过程编程的一种补充和完善;

核心是类和对象的抽象封装和创建,通过创建的各种对象之间互相协作(互相调用函数)完成一个功能的完整流程;

通过面向对象的三大特征封装、继承、多态,来提高程序的健壮性、代码的复用性和功能的强大的扩展性。

1.原生JS中,通过函数来模拟构造函数

构造函数:专门用于被创建对象的函数,函数本身定义一个自定义数据类型,内部通过this来定义各种类型的属性和行为。
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.run = function() { console.log(“锻炼身体”); }
}

构造函数,和new关键字结合起来创建对象

var _obj = new Person(“tom”, 48);


通过对象的引用变量,可以调用对象的属性和行为
console.log(_obj.name);//调用对象的属性
_obj.run()// 调用对象的函数
2.对象的属性和方法
面向对象处理的核心是类和对象

对象具有属性和方法操作,通常情况下,每个独立的对象的属性值不一定相同,但是同一个类型的对象的行为大致一致。

传统函数存在的问题:

  (1)通过构造函数创建的对象,每个对象的数据都是独立的。

  (2)构造函数中定义的对象的行为,构成了闭包函数,闭包函数一旦出现,对象的销毁就会变得非常困难。

  (3)构造函数创建对象时,每个对象都独立拥有构造函数中定义的方法,这样就会造成有多少个对象就会有多少个重复的对象的方法产生。造成系统资源不必要的损耗。

  解决方案:通过构造函数的原型对象prototype来定义公共方法进行处理。
3.构造函数的原型prototype

  每个构造函数都会有一个原型对象prototype

prototype:原型对象,用于给构造函数添加对象公共使用的属性和方法,优化程序!

添加公共属性:

Person.prototype.species = “人类”;
添加公共函数:

Person.prototype.play = function() {console.log(“游戏中”);}
通过Person这个构造函数创建的对象,都默认拥有species属性和play()函数操作

原生JS中的String、Array等内置对象,就是通过这样的方法进行方法扩展的!

4.面向对象的封装

 *在JS中,对于面向对象的争议已经存在很长的时间,不可否认的是面向对象确实是适合项目复杂度较高的情况,    更加有利于项目的高效开发和扩展。

 *所以原生JS中通过构造函数进行面向对象的模拟实现,但是在ES6中JS已经启用了关键字class以及和面向对象相
   关的一系列的使用方式。

 *目前在原生JS中对于对象的封装遵循以下的方式:

通过分析之后抽取出来的构造函数中,只定义属性

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

通过分析之后抽取出来的函数操作,尽量都使用构造函数的prototype来进行定义

Person.prototype.eat = function() { // TODO }
Person.prototype.sleep = function() { // TODO }
Person.prototype.play = function() { // TODO }
5.构造函数继承之apply/call
    1).通过apply/call方法实现构造函数的继承

    2).apply和call方法的核心,是通过参数来修改当前对象中的this指向

    3).Animal(thisArg, arguments)在调用的时候,Animal中的this会被thisArg取代,从而让thisArg指向        Animal中的数据,实现了继承关系

   但是通过apply/call实现的继承,不能继承父类prototype声明的属性或者方法

var Animal = function(type, color) {
  this.type = type;
  this.color = color;
}
var Cat = function(name, age) {
  // Animal.apply(this,[type, color]);
  Animal.call(this, type, color);
  this.name = name;
  this.age = age;
}6.原型继承之prototype
   通过另一种继承方式,通过空对象prototype原型链进行继承
function _extends(Child, Parent) {
  var F = function() {}
  F.prototype = Parent.prototype;
  Child.prototype = new F();
  Child.prototype.constructor = Child;
  Child.super = Parent.prototype;
}封装好继承函数之后,直接进行使用——这也是项目中经常使用的方式!
var Animal = function () {};
var Cat = function() {};
_extends(Cat, Animal);// 实现Cat继承Animal的功能7.直接继承protype  
通过指定类型和被继承类型的prototype进行绑定来实现继承。
通过Prototype原型进行继承,这样的方式是在第二种方式基础上进行的优化。
Animal = function(){}
Animal.prototype.species = “动物”
var Cat = function(name, color) {
  this.name = name;
  this.color = color;
}
Cat.prototype = Animal.prototype;

Cat.prototype.constructor = Cat;

var cat = new Cat(“tom”, “orange”);8.通过空对象进行继承
第三种方式实现了继承,但是继承者和被继承者之间出现了prototype原型共同指向的问题,这里通过一个中间的空对象进行处理,提升代码质量。
var Animal = function() {}
Animal.prototype.species = “动物”;
var Cat = function(name, age) {
  this.name = name;
  this.age = age;
}
var F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;##### 实现了Cat和Animal之间的继承关系
通常在项目应用的时候,将继承关系封装成函数方便调用.
function extends (Child, Parent) {
var F = function() {};//空对象
  F.prototype = Parent.prototype;// 类型prototype关联
  Child.prototype.constructor = Child;// 重新设置
  Child.super = Parent.prototype;// 打开父对象的访问途径
}以上乃是我的片面之解,希望可以帮到大家。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: