javascript中的Function对象和Object对象的区别以及对象继承

    在javascript中一个由函数(也可以称构造函数/构造方法)创建(通常是用new关键字创建或是调用此方法返回一个this对象)出来的对象调用某个方法时,首先是从构造函数中找,构造函数中没有的话就从构造函数的prototype对象中找。用函数创建出来的实例是Object方法的实例。Function是创建函数的方法,Function是Object方法创建出来的,而Object的构造函数又是Function,所以这两个可以看成是相互创建。

下面举例来说说继承关系,看看对象都拥有哪些方法。

  1,构造函数继承 

function SuperClass() {
	this.name = 1;
	this.print = function() {
		alert("print super");
	}
}

function SubClass()  {
	this.super = SuperClass;
	this.super();
	delete this.super;
}

SuperClass和SubClass可以看成是两个类,SuperClass通过new出来的对象具有name属性和print方法。

如:var super = new SuperClass();super.print()

SubClass构造体里将SuperClass作为他的一个成员方法,并且执行了该方法,使得SubClass构造出来的实例拥有了SuperClass中的print方法和name属性。

delete this.super是删除这个对象的super属性,使对象对此方法没有访问权限。

2,对象冒称继承--通过call或者apply方法实现

function SuperClass() {
	this.name = 1;
	this.print = function() {
		alert("print super");
	}
}

function SubClass()  {
	SuperClass.call(this)
}

SubClass中SuperClass.call(this)是指调用下SuperClass这个方法,用call的第一个参数去冒称SuperClass里的this对象,call方法第二个参数和之后的参数对应SuperClass函数接收的参数。如SuperClass.call(this,param,param2)。SubClass中SuperClass.call(this)也可以换成SuperClass.apply(this)。apply的意思call的意思基本上是一致,区别在于apply是用数组接收参数,如SuperClass.apply(this,[param,param2])。call,apply只有通过function关键字或Function创建出来的方法对象、Function、Object能调用。

3,prototype原型对象继承

prototype对象和call、apply方法都是javascript内部特有的,prototype也是只有通过function关键字或Function创建出来的方法对象、Function、Object能调用的属性。

function SuperClass() {
	this.name = 1;
	this.print = function() {
		alert("print super");
	}
}
SuperClass.prototype.say = function() {
	alert(this.name);
}

这样SuperClass构造出来的实例就拥有了say这个方法。因为构造出来的实例在执行say方法时是先从SuperClass构造体中找,找到的话就执行构造体中的say方法,否则就从

SuperClass的prototype对象中找,默认情况下prototype对象是一个Object的实例相当于new Object()或{}。

function SuperClass() {
	this.name = 1;
	this.print = function() {
		alert("print super");
	}
}
SuperClass.prototype.say = function() {
	alert(this.name);
}
function SubClass()  {
	this.subname = 2;
}
SubClass.prototype = new SuperClass();

按照上面分析,SubClass方法构造出来的对象除了有subname这个属性,还将继承SubClass.prototype对象中的属性和方法,也就是具备name、print、say等属性和方法。

Function.prototype = {
		arg:3,
		all:function(){
			alert("所有的方法都有这个all方法和arg属性"+this.arg);
		}};
function SuperClass() {
	this.name = 1;
	this.print = function() {
		alert("print super");
	}
}
SuperClass.prototype.say = function() {
	alert(this.name);
}
function SubClass()  {
	this.subname = 2;
}
SubClass.prototype = new SuperClass();

//测试:
SuperClass.all();
SubClass.all();
Function.all();
Object.all();

按照javascript原型继承法的特点,function关键字或Function创建出来的方法都是Function(他本身也是function)构造出来的实例,如果给Function.prototype注入些方法或属性的话,那么所有的方法都将具有这些方法或属性。

给Function的prototype添加了all方法后,就所有的方法都有all方法,Function和Object本身也是方法,所以他们也有all方法

Object.prototype = {
		arg:3,
		all:function(){
			alert("所有的方法都有这个all方法和arg属性"+this.arg);
		}};
function SuperClass() {
	this.name = 1;
	this.print = function() {
		alert("print super");
	}
}
SuperClass.prototype.say = function() {
	alert(this.name);
}
function SubClass()  {
	this.subname = 2;
}
SubClass.prototype = new SuperClass();

//测试:
SuperClass.all();
SubClass.all();
Function.all();
Object.all();
new SuperClass().all();
new SubClass().all();

如果要让所有对象都具备这样的all的方法就给Object的Prototype注入方法。

上例中SuperClass构造出来的实例也拥有all方法。

 

javascript的继承是用一个对象继承另外一个对象所拥有的属性和方法,跟被继承的对象的构造器没有很直接的关系。因为对象的方法构造器只是决定这个对象创建时所具有的初始属性和方法,而这个对象在以后是可以被修改所拥有的属性和方法(如删除或增加这个对象的某个方法或属性),这就是javascript的动态性,javascript定义变量或传参时并不需要定义参数的具体类型(javascript的弱类型),javascript在运行中验证数据。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript实现继承的方式有以下几种: 1. 原型链继承 优点:简单方便,易于理解和实现。 缺点:父类的引用属性会被多个实例共享,可能会出现意外修改;子类无法向父类构造函数传递参数。 示例代码: ```javascript function Animal() { this.species = 'animal'; } function Cat() {} Cat.prototype = new Animal(); ``` 2. 借用构造函数继承 优点:可以在子类构造函数向父类构造函数传递参数;解决了父类引用属性被多个实例共享的问题。 缺点:无法实现函数的复用。 示例代码: ```javascript function Animal(name) { this.name = name; } function Cat(name) { Animal.call(this, name); } ``` 3. 组合继承 优点:综合了原型链继承和借用构造函数继承的优点,既可以实现函数的复用,又可以向父类构造函数传递参数。 缺点:父类构造函数会被调用两次,造成了一些不必要的消耗。 示例代码: ```javascript function Animal(name) { this.name = name; } Animal.prototype.sayHello = function() { console.log('Hello, my name is ' + this.name); }; function Cat(name) { Animal.call(this, name); } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; ``` 4. 原型式继承 优点:简单方便,可以在不必创建构造函数的情况下实现继承。 缺点:引用属性会被共享,可能会造成意外修改。 示例代码: ```javascript function createObject(obj) { function F() {} F.prototype = obj; return new F(); } var animal = { species: 'animal' }; var cat = createObject(animal); ``` 5. 寄生式继承 优点:可以在不必创建构造函数的情况下实现继承,可以为对象添加专门的方法。 缺点:引用属性会被共享,可能会造成意外修改。 示例代码: ```javascript function createObject(obj) { var clone = Object.create(obj); clone.sayHello = function() { console.log('Hello, my name is ' + this.name); }; return clone; } var animal = { species: 'animal' }; var cat = createObject(animal); ``` 总体来说,不同的继承方式各有优缺点,应根据具体的需求来选择合适的方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值