在JavaScript中模拟类(class)及类的继承关系_javascript技巧

Javascipt语法不支持"类"(class)[es6已经支持],但是有模拟类的方法。今天我主要谈谈Javascipt中模拟“类”的方法及js中继承的总结和回顾。

js中实现“类”与继承,既是重点,又是难点。很多同学可能都对js中“类”与继承都有所了解,但是深入剖析的时候,感觉力不从心、模棱两可。
我们先来总结一下js定义“类”的几种方法:

方法一:构造函数法

这个方法是比较经典的方法,我们会经常见到。生成实例的时候,使用new关键字。类的属性和方法,还可以定义在构造函数的prototype对象之上。

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

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

var person1 = new Person("张三","29","web frontpage manager");
var person2 = new Person("李四","22","doctor");

person1.sayName(); //弹出"张三"
console.log(person2.name)//输出“李四”

方法二:Object.create()法

方法Object.creat()作为new操作符的替代方案是ES5之后才出来的。用这个方法,"类"就是一个对象,不是函数。

var myMammal = {
 name : 'Herb the Mammal',
 get_name : function () {
 return this.name;
 },
 says : function () {
 return this.saying || '';
 }
}

var myCat = Object.create(myMammal);
myCat.name = 'Henrietta';
myCat.saying = 'meow';
myCat.get_name = function () {
 console.log(this.says + ' ' + this.name + this.says);
}

myCat.get_name();

输出:

function () {
 return this.saying || '';
 } Henriettafunction () {
 return this.saying || '';
 }

目前,各大浏览器的最新版本(包括IE9)都部署了这个方法。如果遇到老式浏览器,可以用下面的代码自行部署。

  if (!Object.create) {
    Object.create = function (o) {
       function F() {}
      F.prototype = o;
      return new F();
    };
  }

方法三:极简主义法

封装

这种方法不使用this和prototype,代码部署起来非常简单。 首先,它也是用一个对象模拟"类"。在这个类里面,定义一个构造函数creatFn(),用来生成实例。

  var Dog= {
    creatFn: function(){
      // some code here
    }
  };

然后,在creatFn()里面,定义一个实例对象,把这个实例对象作为返回值。

  var Dog= {
    creatFn: function(){
      var dog= {};
      dog.name = "狗狗";
      dog.makeSound = function(){ alert("汪汪汪"); };
      return dog;
    }
  };

使用的时候,调用creatFn()方法,就可以得到实例对象。

  var dog1 = Dog.creatFn();
  dog1.makeSound(); // 汪汪汪

这种方法的好处是,容易理解,结构清晰优雅,符合传统的"面向对象编程"的构造,因此可以方便地部署下面的特性。

继承

让一个类继承另一个类,实现起来很方便。只要在前者的creatFn()方法中,调用后者的creatFn()方法即可。 先定义一个Animal类。

  var Animal = {
    creatFn: function(){
      var animal = {};
      animal.eat= function(){ alert("吃饭饭"); };
      return animal;
    }
  };

然后,在Dog的creatFn()方法中,调用Animal的creatFn()方法。

  var Dog= {
    creatFn: function(){
      var dog= Animal.creatFn();
      dog.name = "狗狗";
      dog.makeSound = function(){ alert("汪汪汪"); };
      return dog;
    }
  };

这样得到的Dog实例,就会同时继承Dog类和Animal类。

  var dog1= Dog.creatFn();
  dog1.eat(); // 吃饭饭

私有属性和私有方法

在creatFn()方法中,只要不是定义在dog对象上的方法和属性,都是私有的。

  var Dog= {
    creatFn: function(){
      var dog= {};
      var sound = "汪汪汪";
      dog.makeSound = function(){ alert(sound); };
      return dog;
    }
  };

上例的内部变量sound,外部无法读取,只有通过dog的公有方法makeSound()来读取。

  var dog1 = Dog.creatFn();
  alert(dog1.sound); // undefined

数据共享

有时候,我们需要所有实例对象,能够读写同一项内部数据。这个时候,只要把这个内部数据,封装在类对象的里面、creatFn()方法的外面即可。

  var Dog= {
    sound : "汪汪汪",
    creatFn: function(){
      var dog= {};
      dog.makeSound = function(){ alert(Dog.sound); };
      dog.changeSound = function(x){ Dog.sound = x; };
      return dog;
    }
  };

然后,生成两个实例对象:

  var dog1 = Dog.creatFn();
  var dog2 = Dog.creatFn();
  dog1.makeSound(); // 汪汪汪

这时,如果有一个实例对象,修改了共享的数据,另一个实例对象也会受到影响。

  dog2.changeSound("呜呜呜");
  dog1.makeSound(); //呜呜呜

js继承

关于继承,网上也有很多资料可以查询,但是很多朋友对其理解的不够深入。讲到继承,假如你不去查资料,猛地一下,可能说不出个所以然来。这就说明我们的基础知识打的不够扎实。没有理解透彻。今天,我站在前辈的基础之上,再来和大家一起回顾一下这个 继承。

继承最常用的两种方式如下:

  • 原型链继承(对象间的继承)
  • 类式继承(构造函数间的继承)

原型链继承

什么是原型链继承?这里我就不说什么定义了。其实就是用prototype继承父级。

举个例子:

function Parent(){
 this.name = 'mike';
}
function Child(){
 this.age = 12;
}
Child.prototype = new Parent();//Child继承Parent,通过原型,形成链条

var test = new Child();
alert(test.age);
alert(test.name);//得到被继承的属性
//继续原型链继承
function Brother(){ //brother构造
 this.weight = 60;
}
Brother.prototype = new Child();//继续原型链继承
var brother = new Brother();
alert(brother.name);//继承了Parent和Child,弹出mike
alert(brother.age);//弹出12

上面例子,通过原型,形成链条,Child继承了Parent,Brother有继承了Child,最后brother既有Child和Parent的属性,又有自己的属性。这就是原形链的继承。

类式继承(借用构造函数)

类式继承一般是通过运用call或者apply 进行子类型构造函数的内部调用超类型的构造函数。举个例子:

function Parent(age){
 this.name = ['mike','jack','smith'];
 this.age = age;
}

function Child(age){
 Parent.call(this,age);
}
var test = new Child(21);
alert(test.age);//21
alert(test.name);//mike,jack,smith
test.name.push('bill');
alert(test.name);//mike,jack,smith,bill

上面的两种继承是最基本的两种继承方式。

此外还有一些继承方式,我们一起来看一下!

组合继承

组合继承通常是上面两种继承方式组合在一起使用的继承方式。

举例如下:

function Parent(age){
 this.name = ['mike','jack','smith'];
 this.age = age;
}
Parent.prototype.run = function () {
 return this.name + ' are both' + this.age;
};
function Child(age){
 Parent.call(this,age);//对象冒充,给超类型传参
}
Child.prototype = new Parent();//原型链继承
var test = new Child(21);//写new Parent(21)也行
alert(test.run());//mike,jack,smith are both21

原型式继承

和上面讲的原形链式继承只有一字之差,但是不是同一个内容。我们所说的原型式继承,就是我们上节课所讲的,通过Object.create()方式来创建新的类。因为这种方式老式浏览器不支持。因此,假如我们不用Object.create(),也可以有替代法,方式如下:

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

这个函数,就实现了我们Object.create()创建类的方式!

因此举例如下:

 function obj(o){
 function F(){}
 F.prototype = o;
 return new F();
 }
var box = {
 name : 'trigkit4',
 arr : ['brother','sister','baba']
};
var b1 = obj(box);
alert(b1.name);//trigkit4

b1.name = 'mike';
alert(b1.name);//mike

alert(b1.arr);//brother,sister,baba
b1.arr.push('parents');
alert(b1.arr);//brother,sister,baba,parents

var b2 = obj(box);
alert(b2.name);//trigkit4
alert(b2.arr);//brother,sister,baba,parents

寄生式继承

举例如下:

function creatAnother(original){
 var clone=new Object(original);
 clone.sayHi=function(){
 alert("hi")
 };
 return clone;
}
var person={
 name:"haorooms",
 friends:["hao123","zhansan","lisi"]
}

var antherPerson=creatAnother(person);
antherPerson.sayHi();//hi

寄生组合式

function inheritPrototype (subType,superType) {
 var prototype = Object.creat(superType.prototype);
 prototype.constructor = subType;
 subType.prototype = prototype;
};

function SuperType (name) {
 this.name = name;
 this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function () {
 console.log(this.name);
}
function SubType(name, age) {
 //继承属性
 SuperType.call(this,name);
 this.age = age;
}
//继承方法
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function () {
 console.log(this.age);
}

var instance = new SubType();

类的继承,基本上就是如上几种方式。下面再简单的说一下ES6的class类吧!

es6实现类

//定义类
class Point {
 constructor(x, y) {
 this.x = x;
 this.y = y;
 }
 toString() {
 return '('+this.x+', '+this.y+')';
 }
}
var point = new Point(2, 3);
point.toString() // (2, 3)
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true

Class的继承

class ColorPoint extends Point {
 constructor(x, y, color) {
 super(x, y); // 调用父类的constructor(x, y)
 this.color = color;
 }
 toString() {
 return this.color + ' ' + super.toString(); // 调用父类的toString()
 }
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索javascript
, 继承
, class

javascript class、javascript 添加class、javascript classname、javascript addclass、javascript 修改class,以便于您获取更多的相关知识。

时间: 2024-10-24 14:34:13

在JavaScript中模拟类(class)及类的继承关系_javascript技巧的相关文章

JavaScript中使用ActiveXObject操作本地文件夹的方法_javascript技巧

在Windows平台上, js可以调用很多Windows提供的ActivexObject,本文就使用js来实现文档处理, 和使用js编写ActiveX做一个简单介绍. 复制代码 代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html> <head>  <t

浅析JavaScript中的变量复制、参数传递和作用域链_javascript技巧

今天在看书的过程中,又发现了自己目前对Javascript存在的一个知识模糊点:JS的作用域链,所以就通过查资料看书对作用域链相关的内容进行了学习.今天学习笔记主要有这样几个关键字:变量.参数传递.执行环境.变量对象.作用域链. 1.变量 变量需要注意的有两点:变量声明和复制变量值. 变量声明肯定大家都很熟悉,在JS中我们都是通过 var 关键字进行变量声明的.JS中规定,通过var声明的变量会被添加到最近的环境中,如果声明并且初始化一个变量没有用到var关键字,这个变量会被添加到全局环境中.

Javascript中apply、call、bind的巧妙使用_javascript技巧

apply.call 在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. JavaScript 的一大特点是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念. 先来一个栗子: function fruits() {} fruits.prototype = { color: "red", say: function() { console

JavaScript中数组的22种方法必学(推荐)_javascript技巧

前面的话 数组总共有22种方法,本文将其分为对象继承方法.数组转换方法.栈和队列方法.数组排序方法.数组拼接方法.创建子数组方法.数组删改方法.数组位置方法.数组归并方法和数组迭代方法共10类来进行详细介绍 对象继承方法 数组是一种特殊的对象,继承了对象Object的toString().toLocaleString()和valueOf()方法 [toString()] toString()方法返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串 [注意]该方法的返回值与不使用任何参数

JavaScript中的对象继承关系_javascript技巧

我们今天就来看一下继承中的类继承以及类继承和原型继承的混用,所谓类继承,就是使用call或者apply方法来进行冒充继承: function Desk(size,height){ this.size=size; this.height=height; } function MJDesk(size,height){ Desk.call(this,size,height);//这种就叫类继承. } var mj = new MJDesk(10,123); 像上面这种就是我们要使用的类继承,用这种继承

Javascript中的方法和匿名方法实例详解_javascript技巧

本文实例讲述了Javascript中的方法和匿名方法.分享给大家供大家参考.具体分析如下: Javascript方法(函数) 声明函数 以function开头,后跟函数名,与C#.java不同,Javascript不需要声明返回值类型.参数类型.没有返回值就是undefined. 举个例子更清楚:  无参数无返回值的方法: function f1(){ alert('这是一个方法'); } f1();//调用方法 无参数有返回值的方法: function f2(){ return 100; }

JavaScript中如何通过arguments对象实现对象的重载_javascript技巧

复制代码 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript"> /* *1.js 中不存在函数的重载 2.js函数定义时候的形参个数,和执行时候时,传递的实参的个数可以不一样. 3.js执行时

JavaScript中的new的使用方法与注意事项_javascript技巧

原文: JavaScript, We Hardly new Ya  --Douglas Crockford.    http://yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/ 引用 JavaScript是一门基于原型的语言,但它却拥有一个 new 操作符使得其看起来象一门经典的面对对象语言.那样也迷惑了程序员们,导致一些有问题的编程模式. 其实你永远不需要在JavaScript使用 new Object().用字面量的形式{}去

Javascript 中 null、NaN和undefined的区别总结_javascript技巧

1.类型分析: js中的数据类型有undefined,boolean,number,string,object等5种,前4种为原始类型,第5种为引用类型. 代码 复制代码 代码如下: var a1; var a2 = true; var a3 = 1; var a4 = "Hello"; var a5 = new Object(); var a6 = null; var a7 = NaN; var a8 = undefined; alert(typeof a); //显示"u