2020-12-15 Javascript定义类(class)的三种方式

2020-12-15 Javascript定义类class的三种方式

在面向对象编程中,类(class)是对象(object)的模板,定义了同一组实例共有的属性和方法,Javascript中有三种定义类的方法:构造函数法、Object.create()、极简主义法

一、构造函数法

用构造函数模拟“类”,在其内部用this关键字指代实例对象
所谓“构造函数”,其实就是一个普通函数,但是在其内部使用了this变量,对构造函数使用new运算符,生成实例,并且this变量会绑定在实例对象上

function Cat(name,color){
 this.name=name;
 this.color=color;
}
// 生成实例对象
var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");
alert(cat1.name); // 大毛
alert(cat1.color); // 黄色

上面的cat1和cat2会有一个constructor属性,指向其构造函数

alert(cat1.constructor == Cat); //true
alert(cat2.constructor == Cat); //true

此外,还有instanceof运算符,验证原型对象与实例对象之间的关系

alert(cat1 instanceof Cat); //true
alert(cat2 instanceof Cat); //true

构造函数模式存在的问题就是资源浪费,浪费内存
每个构造函数都有一个prototype属性,指向另外一个对象,这个对象的所有属性和方法,都会被构造函数的实例继承,这意味着可以把那些不变的属性和方法直接定义在prototype对象上
isPrototypeOf():这个方法用来判断某个prototype对象和某个实例之间的关系

alert(Cat.prototype.isPrototypeOf(cat1)); //true

hasOwnPrototype():这个方法用来判断某一个属性到底是本地属性还是继承自prototype对象的属性

alert(cat1.hasOwnProperty("name")); // true
alert(cat1.hasOwnProperty("type")); // false

in:此运算符用来判断某个实例是否含有某个属性,不管是不是本地属性,用来遍历某个对象的所有属性

alert("name" in cat1); // true
alert("type" in cat1); // true

二、Object.create()法

为了解决“构造函数”的缺点,EMCAScript提出了一个新的方法Object.create(),用这个方法,类就是一个对象,不是函数

var Cat = {
  name: "大毛",
  makeSound: function(){ alert("喵喵喵"); }
};

然后直接用Object.create()生成实例,不需要用到new

var cat1 = Object.create(Cat);
console.log(cat1.name); // 大毛
cat1.makeSound(); // 喵喵喵

遇到浏览器不支持的,用以下代码自行部署

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

这种方法比“构造函数法”要简单,但是不能实现私有属性和私有方法,实例对象之间也不能共享数据,对“类”的模拟不够全面

三、极简主义法

封装:这种方法不使用this和prototype,也是一个对象模拟“类”,在这个类里面,定义一个构造函数createNew(),用来生成实例,然后在createNew()里面定义一个实例对象,把这个实例对象作为返回值

var Cat = {
	createNew: function(){
		var cat = {};
		cat.name = "大毛";
		cat.makeSound = function(){alert("喵喵喵")};
		return cat;
	}
};

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

var cat1 = Cat.createNew();
cat1.makeSound(); // 喵喵喵

这种方法的好处是容易理解,结构清晰优雅,符合传统的“面向对象编程”的构造,可以很好的实现继承、私有属性和私有方法、数据共享

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

var Animal = {
	createNew: function(){
		var animal = {};
		animal.sleep = function(){alert("睡懒觉")};
		return animal;
	}
};

然后在Cat的createNew()方法中,调用Animal的createNew()方法

var Cat = {
	createNew: function(){
		var cat = Animal.createNew();
		cat.name = "大毛";
		cat.makeSound = function(){alert("喵喵喵")};
		return cat;
	}
};

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

var cat1 = Cat.createNew();
cat1.sleep(); // 睡懒觉
cat1.makeSound(); // 喵喵喵

私有属性和私有方法:在createNew()方法中,只要不是定义在cat对象上的方法和属性都是私有的

var Cat = {
	createNew: function(){
		var cat = {};
		car sound = "喵喵喵";
		cat.makeSound = function(){alert(sound)};
		return cat;
	}
};

上面的内部变量sound,外部是无法读取的,只有通过cat的公有方法makeSound()获取

var cat1 = Cat.createNew();
console.log(cat1.sound); // undefined
cat1.makeSound(); // 喵喵咪

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

var Cat = {
	sound: "共享数据",
	createNew: function(){
		var cat = {};
		cat.makeSound = function(){alert(Cat.sound)};
		cat.changeSound = function(x){Cat.sound = x;};
		return cat;
	}
};

然后,生成两个实例对象

var cat1 = Cat.createNew();
var cat2 = cat.createNew();
cat1.makeSound(); // 共享数据

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

cat2.changeSound("喵喵喵");
cat1.makeSound(); // 喵喵喵
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值