javascript类继承系列三(对象伪装)

原理:在子类的构造器上调用超类构造器(父类构造器中的this指向子类实例),js提供了apply()和call()函数,可以实现这种调用

function baseClass() { this.colors = ['red', 'blue']; }
//在子类构造器调用父类构造器
function childClass() { baseClass.call(this); }
var instanse1 = new childClass();
var instanse2 = new childClass();
instanse2.colors.push('green');
var instanse3 = new childClass();
alert(instanse1.colors);//red,blue
alert(instanse2.colors);//red,blue,green
alert(instanse3.colors);//red,blue
//结果是:即使对某个继承的实例进行修改,对其他实例也没影响,核心是子类构造器的 call()执行,与之相同功能的还有apply()
// 二者作用:
// js每个funciton都有call和apply方法,call函数的功能是在指定的对象上执行函数,它的第一个参数就是指定的对象,还可以有多个参数,除第一个参数之外,其他参数都是指定对象所需的参数
function fun(x, y) { this.pointX = x; this.pointY = y;}
var dot = {};
fun.call(dot, 10, 20);
alert(dot.pointX);
alert(dot.pointY);
其中fun.call(dot,10,20);使dot具有了fun的属性,意思是在dot上运行fun(),在运行时,fun中的this指向dot,同时向fun()传递了两个参数,
apply与call功能相同,但是调用形式不同

//使用apply调用
fun.apply(dot, [30, 40]);
alert(dot.pointX);
alert(dot.pointY);

fun()调用所需的参数以数组形式传递给形参了,再参数不确定用apply最合适了
所以如果函数传递参数是固定的,用call或者apply都可以,如果不固定用apply()

function fun2(x, y, z) {
x = x || 0;
y = y || 0;
z = z || 0;
var list = [];
list.push(x);
list.push(y);
list.push(z);
alert(list);
}
fun2(1, 2, 3);
function fun1() { fun2.apply(this, arguments); }
fun1(10);
fun1(10, 20);
fun1(10, 20, 30);

-------------------------------------------------------

function BaseClass(n, g) {
this.Name = n;
this.Gender = g;
this.getName = function () { return this.Name;}
}
BaseClass.prototype.GetGender = function () { return this.Gender; }
function ChildClass(n, g, m) {
BaseClass.call(this, n, g);
this.age = m;
}
ChildClass.prototype.GetAge = function () { return this.age; }
var instanse1 = new ChildClass('a', 'M', 20);
alert(instanse1.getName());
alert(instanse1.GetAge());
alert(instanse1.GetGender());//报错
//GetGender未被继承,说明仅靠构造函数实现继承不可靠,应该使用原型
//getName()是定义在构造函数里面的,意味着每次创建父类对象或者子类对象,这个方法都就会被重复创建一遍,而这种重复工作,是我们应该避免的,很多时候,我们将属性定义在构造器里面,将方法定义在原型对象上,
因为每个对象拥有不同的属性,但拥有相同的方法,

原文地址:https://www.cnblogs.com/niuzaihenmang/p/5600671.html