`

call和apply的区别

阅读更多

      我们在项目中经常使用call或者apply来继承某个类的实例属性和方法。但是你知道两者的却区别是什么吗?了解两者的区别,有助于你正确的选择使用call还是apply。

      在javascript中call方法和apply方法调用产生的效果是一样的,只是语法(参数)不一样。

目录:

  1、call和apply的区别,然后实例演示

  2、call和apply的常用应用场合

  3、call和apply不能继承原型的属性和方法

  4、怎样继承原型的属性和方法

 

1、call和apply的区别,然后实例演示

 call语法如下:

      obj.call(要替换的执行环境,参数1, 参数2,……,参数n);

 【实例】创建Person类,接收name和age两个参数及提供getName()和getAge()方法。然后创建一个Student对象从Person中继承name和age实例属性和方法。

// Person构造函数
function Person(name, age){
	this.name = name;
	this.age = age;
	// 添加方法到原型
	if (typeof Person.prototype.getName != "function") {
		Person.prototype.getName = function(){
			return this.name;
		};
		Person.prototype.getAge = function(){
			return this.age;
		}
	}
}
// Student构造函数
function Student(name, stuNum, age, qq){
	this.stuNum = stuNum;
	this.qq = qq;
	// 继承Person类的实例属性
	Person.call(this, name, age);
}

var stu = new Student("administritor", "No.1001", 23, "1840554");
alert([stu.name, stu.age]); // 结果:administritor,23

 

apply语法如下:

      object.apply(要替换的执行环境,[参数1, 参数2,……,参数n ]);

 【实例】创建Person类,接收name和age两个参数及提供getName()和getAge()方法。然后创建一个Student对象从Person中继承name和age实例属性和方法。

// Person的构造函数
function Person(name, age){
	this.name = name;
	this.age = age;
	// 添加方法到原型
	if (typeof Person.prototype.getName != "function") {
		Person.prototype.getName = function(){
			return this.name;
		};
		Person.prototype.getAge = function(){
			return this.age;
		}
	}
}
// Student的构造函数
function Student(name, stuNum, age, qq){
	this.stuNum = stuNum;
	this.qq = qq;
	// 继承Person类的实例属性
	Person.apply(this, [name, age]);
}

var stu = new Student("administritor", "No.1001", 23, "1840554");
alert([stu.name, stu.age]); // 结果:administritor,23

从上面实例可以看出,call和apply的主要区别是在指定调用object对象时传递构造参数的方式。call使用的类似java中的可变参数,即将构造参数一次排在“要替换的执行环境”后面。apply则使用一个数组将构造参数进行包装,然后传递。

 

2、call和apply的常用应用场合

【实例】如果Person对象的构造参数和Student对象的构造参数完全一样(包括顺序)。此时,我们应该选择call还是apply呢?由于apply接收一个数组、Person和Student的构造参数一样且arguments也是一个数组。则,我们可以直接用:object.apply(this, arguments);就可进行继承。但是有人说,call也可以啊。我直接将参数依次写在object.call(this, arg1, arg2,...,argn)。如果Person和Student的参数有n个,则你需要写多少呢,你能保证你不会把顺序写错,你觉得代码可读性好吗?因此,如果被继承和继承的构造函数一样(包括参数顺序),则推荐使用apply方式。

// Person构造函数
function Person(name, age){
	this.name = name;
	this.age = age;
	// 添加方法到原型
	if (typeof Person.prototype.getName != "function") {
		Person.prototype.getName = function(){
			return this.name;
		};
		Person.prototype.getAge = function(){
			return this.age;
		}
	}
}
// Student构造函数
function Student(name, age){
//	Person.apply(this, [name, age]);
	// 同上
	Person.apply(this, arguments);
	if (typeof Student.prototype.setName != "function") {
		Student.prototype.setName = function(name){
			this.name = name;
		};
		Student.prototype.setAge = function(age){
			this.age = age;
		};
	}
}

// 测试
var stu = new Student("administritor", 23);
alert([stu.name, stu.age]);
stu.setName("operation");
stu.setAge(41);
alert([stu.name, stu.age]);

如果Person和Student的参数不一样,则两种方式你就选择你自己喜欢的方式。

// Person构造函数
function Person(name, age){
	this.name = name;
	this.age = age;
}
// 方式一:
function Student(name, sex, age, email){
	this.sex = sex;
	this.email = email;
        Person.call(this, naem, age);
}

方式二:
function Student(name, sex, age, email){
	this.sex = sex;
	this.email = email;
	Person.apply(this, [name, age]);
}
3、call和apply不能继承原型的属性和方法
在上面的Person和Student例子中如果调用Person的getName()和getAge()方法,则会抛出”对象不支持属性和方法“错误;
代码如下:
function Person(name, age){
	this.name = name;
	this.age = age;
	// 添加方法到原型
	if (typeof Person.prototype.getName != "function") {
		Person.prototype.getName = function(){
			return this.name;
		};
		Person.prototype.getAge = function(){
			return this.age;
		}
	}
}

function Student(name, stuNum, age, qq){
	this.stuNum = stuNum;
	this.qq = qq;
	Person.call(this, name, age);
}

var stu = new Student("administritor", "No.1001", 23, "1840554");
alert([stu.getName(), stu.getAge()]);
 为什么呢?
我们先看一下call和apply的运行方式。当执行Person.call(this, name, age); 这行代码时,实际是将Person构造函数内部的this替换成Student的,相当于将Person中的this.name=name;this.age=age;两行代码移植到Student构造函数内部。所以我们可以通过Student的实例访问name和age的原因。为什么不能访问Person.prototype上面的getName()和getAge()方法呢?我认为是,call或apply只是替换了Person中的this,而且Student自己存在Student.prototype。依照js的变量搜索方法,先在Student.prototype,如果不存在,则在Person中去找Person.prototype。
4、怎样继承原型的属性和方法
要继承原型中的属性和方法,则只能通过原型链方式进行继承。如:
Student.prototype = new Person("zhangsan", 23);
调用了该语句后,Student的实例对象就可以调用Person.prototype的getName和getAge方法了。为什么呢?
调用Student.prototype = new Person("zhangsan", 23);前的模型如下图:


调用后:

 如果现在要在Student的实例上调用getName(),则搜索路径如下:
1、现在Student中查找,如果找到则返回。否则,执行2
2、在Student的原型中查找,如果找到则返回。否则,执行3
3、在Student的原型的原型中找(Person的原型中找),如果找到则返回。否则,执行4。
4、在Object中查找,如果找到则返回,否则,抛出”对象没有属性和方法“错误。
注意:2和3步依次类推,直到Object。
【实例】实现实例属性和原型方法的继承。
// Person的构造方法
function Person(name, age){
	this.name = name;
	this.age = age;
	
	if (typeof Person.prototype.getName != "function") {
		Person.prototype.getName = function(){
			return this.name;
		};
		Person.prototype.getAge = function(){
			return this.age;
		}
	}
}
// Student的构造方法
function Student(name, stuNum, age, qq){
	this.stuNum = stuNum;
	this.qq = qq;
	// 继承实例属性和方法
	Person.call(this, name, age);
}
// 继承原型的属性和方法
Student.prototype = new Person();

var stu = new Student("administritor", "No.1001", 23, "1840554");
alert([stu.getName(), stu.age]);
今天就到此。如果有不正确的地方,请批评指正,谢谢!
  • 大小: 11.7 KB
  • 大小: 14.6 KB
分享到:
评论

相关推荐

    JavaScript中call与apply方法

    JavaScript中call与apply方法

    call与apply区别 详细解读.pdf

    call与apply区别详细解读 call和apply是JavaScript中的两个重要方法,它们都是Function.prototype中的方法,这意味着每个函数都可以使用这两个方法。它们的作用是改变函数体内的this对象的值,以扩充函数赖以运行的...

    关于Javascript中call与apply的进一步探讨

    在JavaScript中,`call`和`apply`是两个非常重要的方法,它们都用于改变函数调用时的上下文(即`this`的值),并且可以灵活地传递参数。本篇文章将深入探讨这两个方法的用法、区别以及实际应用场景。 `call`方法...

    Javascript call和apply区别及使用方法

    ### Javascript call和apply区别及使用方法 在JavaScript中,`call`和`apply`方法被用于显式地设定函数体内`this`的值,这是所谓的函数借用(method borrowing)或函数上下文改变(context changing)。它们使得一...

    理解JavaScript的caller callee call apply

    ### 理解JavaScript中的`caller`...综上所述,理解`caller`、`callee`、`call`、`apply`以及`arguments`对象在JavaScript编程中至关重要,它们不仅增强了函数的灵活性和复用性,还提供了深入分析和调试代码的强大工具。

    07-call、apply、bind三者的异同.html

    07-call、apply、bind三者的异同

    JavaScript中call和apply方法的区别实例分析

    本文实例分析了JavaScript中call和apply方法的区别。分享给大家供大家参考,具体如下: 这两个方法不经常用,但是在某些特殊场合中是非常有用的,下面主要说下它们的区别: 1、首先,JavaScript是一门面向对象的语言...

    javascript中apply和call方法的作用及区别说明

    一、call和apply的说明 1、call,apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例(就是每个方法)都有call,apply属性。既然作为...

    详解js中call与apply关键字的作用

    通过call和apply可以调用某个函数,并且显式地指定该函数内部的this变量的值。 ### call和apply的基本概念 call方法接受一个参数列表,而apply方法接受一个包含多个参数的数组。两者第一个参数都是要设置为函数...

    js中call与apply的用法小结

    `call` 和 `apply` 的区别 两者的本质区别在于传递参数的方式:`call`接收参数列表,而`apply`接收一个包含参数的数组。在某些场景下,比如当你不确定参数数量或者参数是动态生成的时候,`apply`可能更为灵活。 #...

    JS中的call、apply、bind方法详解.pdf

    1. call和apply的区别在于传递参数的方式,call方法需要一个一个传递参数,而apply方法则直接传递一个数组。 2. call和apply方法直接执行函数,而bind方法需要再次调用。 3. bind方法返回一个新的函数,而call和...

    浅谈javascript中的call、apply、bind_.docx

    bind 方法是 ES5 新增的一个方法,它的传参和 call 类似,但又和 call/apply 有着显著的不同,即调用 call 或 apply 都会自动执行对应的函数,而 bind 不会执行对应的函数,只是返回了对函数的引用。 粗略一看,...

    javascript中call和apply方法浅谈

    总结一下`call`和`apply`的主要区别: 1. `call`允许你直接传递参数列表,每个参数之间用逗号分隔。 2. `apply`要求你提供一个数组或类数组对象,其中的元素作为参数传递。 这两种方法在很多场景下可以互换使用,...

    Js的call与apply1

    JavaScript中的`call`和`apply`是两种非常关键的方法,它们允许我们改变函数内部`this`的指向,同时也为实现模拟继承提供了可能。虽然JavaScript不直接支持类继承,但通过`call`和`apply`,我们可以实现类似的效果。...

    Javascript中call,apply,bind方法的详解与总结

    本文针对JavaScript中三个重要的函数方法——call、apply和bind,进行详尽的分析,并在文章的结尾部分对这三个方法之间的联系和区别进行了概括,以便于读者更深入地理解它们的用途和应用场景。 首先,我们来探讨...

    Javascript - 全面理解 caller,callee,call,apply (转载)

    `call`和`apply`的主要区别在于传递参数的方式:`call`接受一个参数列表,而`apply`接受一个包含参数的数组。 `call`方法允许我们改变函数调用的上下文(即`this`值),并直接传入参数: ```javascript function ...

    详解js中call与apply关键字的作用.docx

    - `apply`和`call`的主要区别在于传递参数的方式。`apply`的第二个参数必须是一个数组或者类数组对象,它的元素会被作为单独的参数传递给函数。 - 在示例中,`func.apply(null,[1,2,3])`和`func.call(null,1,2,3)`...

    Javascript 中的 call 和 apply使用介绍

    还有一点是,虽然call和apply在功能上相似,但在参数处理上有所区别,这一点在处理不确定数量的参数时尤其重要。如果函数的参数数量是固定的,那么使用call和apply可以随意选择。但是,如果参数数量是可变的,或者你...

    js中call与apply的用法小结.docx

    在JavaScript中,`call`和`apply`是两个非常重要的函数,它们都允许开发者改变函数执行时的上下文,即`this`的指向。这两个方法主要用于实现函数的绑定和继承,以及处理数组或类数组对象。 首先,我们来看`call`的...

Global site tag (gtag.js) - Google Analytics