JavaScript面向对象(收集整理)
Posted 自行脑补
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript面向对象(收集整理)相关的知识,希望对你有一定的参考价值。
(1)封装
首先理解构造函数:所谓"构造函数",其实就是一个普通函数,但是内部使用了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
构造函数存在一个弊端:浪费内存,比如:
function Cat(name,color){ this.name = name; this.color = color; this.type = "猫科动物"; this.eat = function(){alert("吃老鼠");}; } var cat1 = new Cat("大毛","黄色"); var cat2 = new Cat ("二毛","黑色");
alert(cat1.eat == cat2.eat); //false
其中前两个属性name,color是实例独自拥有的,cat1和cat2的name,color是不同的,而type,eat()确是可以共同拥有的,所有可以把共有的方法,属性定义在prototype
对象上,如下:
function Cat(name,color){ this.name = name; this.color = color; } Cat.prototype.type = "猫科动物"; Cat.prototype.eat = function(){alert("吃老鼠")}; var cat1 = new Cat("大毛","黄色"); var cat2 = new Cat("二毛","黑色"); alert(cat1.eat == cat2.eat); //true
这时所有实例的type
属性和eat()
方法,其实都是同一个内存地址,指向prototype
对象,因此就提高了运行效率。
(2)继承
function Animal(){ this.species = "动物"; } function Cat(name,color){ this.name = name; this.color = color; }
(Cat要继承Animal)
1.构造函数绑定
使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行
function Cat(name,color){ Animal.apply(this, arguments); this.name = name; this.color = color; } var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
2. prototype模式
将Cat(子)的prototype指向Animal(父)的实例,那么Cat所创建出来的实例就都继承了Animal
Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
其中第二行代码 Cat.prototype.constructor = Cat; 是因为如果原本constructor本来是指向自己的构造函数cat()的,但是这里被赋值给了new Animal(),换了个新构造函数,所以为了不造成继承链的紊乱,必须手动修改回来
3. 直接继承prototype
Cat不变的属性或方法可以直接写入Animal.prototype,然后Cat.prototype = Animal.prototype直接继承
function Animal(){ } Animal.prototype.species = "动物"; Cat.prototype = Animal.prototype; Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
这样的好处是,对比方法2中,不用执行和建立Animal()的实例,也省了内存;
这样的缺点是,由于Cat.prototype = Animal.prototype,Cat.prototype和Animal.prototype现在指向了同一个对象,实际上把Animal.prototype对象的constructor属性也改掉了!
4.利用空对象作为中介
用一个F空对象,几乎不占内存,作为中间桥梁,修改Cat的prototype对象,就不会影响到Animal的prototype对象。
var F = function(){}; F.prototype = Animal.prototype; Cat.prototype = new F(); Cat.prototype.constructor = Cat;
可以封装成一个函数:
function extend(Child,Parent){ var F = function (){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.construction = Child; Child.uber = Parent.prototype; //假设一个Child不变的属性uber } extend(Cat,Animal); var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
5.拷贝继承
把父对象的所有属性和方法,拷贝进子对象
function Animal(){} Animal.prototype.species = "动物"; function extend2(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; } extend2(Cat, Animal); var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
(3)非构造函数继承
1.object()方法
var Chinese = { nation:‘中国‘ }; var Doctor ={ career:‘医生‘ }
如何使Doctor对象继承Chinese对象?
function object(o) { function F() {} F.prototype = o; return new F(); }
var Doctor = object(Chinese); Doctor.career = ‘医生‘; alert(Doctor.nation); //中国
2.浅拷贝:
只是拷贝基本类型的数据
function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } c.uber = p; return c; } var Doctor = extendCopy(Chinese); Doctor.career = ‘医生‘; alert(Doctor.nation); // 中国
Chinese.birthPlaces = [‘北京‘,‘上海‘,‘香港‘];
var Doctor = extendCopy(Chinese);
Doctor.birthPlaces.push(‘厦门‘);
alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
alert(Chinese.birthPlaces); //北京, 上海, 香港, 厦门
下面的代码显露出钱浅拷贝的缺点,就是假如父对象的某个属性也是数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。
3.深拷贝
jQuery库使用的就是这种继承方法。
function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === ‘object‘) { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; } var Doctor = deepCopy(Chinese); Chinese.birthPlaces = [‘北京‘,‘上海‘,‘香港‘]; Doctor.birthPlaces.push(‘厦门‘); alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门 alert(Chinese.birthPlaces); //北京, 上海, 香港
以上内容均参考自:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html
以上是关于JavaScript面向对象(收集整理)的主要内容,如果未能解决你的问题,请参考以下文章
精心收集的 48 个 JavaScript 代码片段,仅需 30 秒就可理解