JavaScript closure: difference between call and apply as well as use them to create inheritance

原创 2016年08月29日 19:35:50

Resume

Today, in an interview, speaking of closure, the interviewer asked me about the difference between call() and apply(). And I didn’t use them before. After searching for a while, I found that we can implement completely a class with JavaScript. We can implement a constructor by using call() and apply(). I thought that we can only implement a class without any inheritance before. This passage will describe what I have found.


call()

Syntax:
function.call(thisArg, arg1, arg2, ...)


Suppose we have a function like this,

var lang = {'languages':['Python', 'Haskell', 'C++', 'Java']};
var favoriteLanguages = function(){
    for(var i = 0; i < this.languages.length; i++){
        console.log('My favorite languages is', this.languages[i]);
    }
}
favoriteLanguages.call(lang);

and it will print

My favorite languages is Python
My favorite languages is Haskell
My favorite languages is C++
My favorite languages is Java

on console.


So, consequently we can say that function.call() will apply arguments to function as local variable.


apply()

Syntax:
fun.apply(thisArg, [argsArray])



Actually it’s quite simular to call(). The only difference is we pass arguments call() while we pass an argument and a list of argument to apply().
Moreover, usually we pass this as the first argument to apply.
It’s all the same when we do:

var lang = {'languages':['Python', 'Haskell', 'C++', 'Java']};
var favoriteLanguages = function(){
    for(var i = 0; i < this.languages.length; i++){
        console.log('My favorite languages is', this.languages[i]);
    }
}
favoriteLanguages.applu(lang);//We changed here.



But when we try to do something different, there will be some differences.

var languages= {'prog_languages':['Python', 'Haskell', 'C++', 'Java'],'languages':['English', 'Français', '中文']};

var prog_l = function(){
    for(var i = 0; i < this.prog_languages.length; i++){
        console.log('I like', this.prog_languages[i], 'as a programming language.');
    }
}

var lang = function(){
    for(var i = 0; i < this.languages.length; i++){
        console.log('I like', this.languages[i], 'as a language.');
    }
}

var dispatch = function(method0, args0, method1, args1){
    method0.apply(args0);
    method1.apply(args1);
};

dispatch(lang,languages,prog_l,languages);

When we run codes above, it will show

I like English as a language.
I like Français as a language.
I like 中文 as a language.
I like Python as a programming language.
I like Haskell as a programming language.
I like C++ as a programming language.
I like Java as a programming language

in console.


It means that when we are not certain how many parameters we will pass, it’s better to use apply() than call(). Because apply() put the first argument into this and take the send argument which is a list as arguments applying to function.


Inheritance

Actually it’s a little bit like the object principle in most programming languages such as Java and C++.
Let’s see an example on mozilla.org.

function Product(name, price) {
    this.name = name;
    this.price = price;
    if (price < 0) {
        throw RangeError('Cannot create product ' + this.name + ' with a negative price');
    }
}

function Food(name, price) {
    Product.call(this, name, price);
    this.category = 'food';
}

function Toy(name, price) {
    Product.call(this, name, price);
    this.category = 'toy';
}

var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);

console.log(cheese.price);

When we run these codes, it will return 5 which is exactly the price of cheese.
But why?
When we instantiate Food, then we jump into the function Food(name, price), then we invoke the function Product.call(this, name, price) and pass this to Product(name, price). In Product(name, price), actually we are modifying Food, because we passed this in Product.call(this, name, price). So that this points to object Food. And we assign name and price to this(which is the reference of Food).
So, it’s the object Food which is being modified and finally we have name, price and category in Food.


Pretty like in Java, isn’t it?
In Java, we may write

class Product{
    protected String name;
    protected int price;
    public Product(String name, int price){
        this.name = name;
        this.price = price;
        if (price < 0) {
            throw new RangeError('Cannot create product ' + this.name + ' with a negative price'); //RangeError is not defined, because it's not important in this case.
        }
    }
}

and

class Food extends Product{
    protected String category = "food";
    public Food(String name, int price){
        super(name, price);
    }
}

References

版权声明:本文章禁止商业使用,非商用转载必须注明出处和作者。作者保留一切权利。

Is punishment necessary to help children learn the difference between right and wrong?

To tell you the truth, I strongly supportthe view that punishment is dispensable for helping childre...
  • w5688414
  • w5688414
  • 2017年07月22日 17:33
  • 269

【JS】The differences between 基本类型 and 引用类型

5个基本数据类型:Undefined、Null、Boolean、Number、String;引用类型:var person = new Object();这里的person就是一个引用类型的变量,他的...
  • qq_27359091
  • qq_27359091
  • 2016年06月03日 22:08
  • 412

【zk开发】use和apply的区别

use 使用一个组件类,该类必须是当前组件对应接口的实现。 zul页面上的所有标准组件 后台都对应一个默认类, 如果use属性非空,那么zk会创建use属性关联的类的一个 实例替代默认类实...
  • gaozhlzh
  • gaozhlzh
  • 2011年10月26日 14:38
  • 2729

What is the difference between call and apply?(关键词:call/apply/invoke)

原文链接: 1.What is the difference between call and apply?
  • qq_33528613
  • qq_33528613
  • 2017年09月10日 21:25
  • 47

JavaScript 中的 this 用法以及 call(apply) 的理解

想要深入了解 JavaScript 这门语言,一个必须掌握的知识点就是对 `this` 的理解。其中, `call` 和 `apply` 又与 `this` 有着密切的联系。趁现在有空,在网上看了一些...
  • gertYY
  • gertYY
  • 2017年02月13日 13:53
  • 2251

the different between call and apply in javascript

function sayColor(spre, ssuf) {alert(spre + this.color + ssuf);}; var obj = new Object(); obj.color ...
  • largetalk
  • largetalk
  • 2011年08月23日 13:12
  • 464

JavaScript中bind、call、apply函数用法详解

在给我们项目组的其他程序介绍 js 的时候,我准备了很多的内容,但看起来效果不大,果然光讲还是不行的,必须动手。前几天有人问我关于代码里 call() 函数的用法,我让他去看书,这里推荐用js 写服务...
  • chenleixing
  • chenleixing
  • 2015年03月14日 14:14
  • 6178

The difference between the request time and the current time is too large.

报错信息: [Error Code]:RequestTimeTooSkewed, [Message]:The difference between the request time and the ...
  • hraceo
  • hraceo
  • 2017年01月09日 11:07
  • 1011

JavaScript 中的 call() 和 apply() 方法深入理解

1、方法定义 call方法:  语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]])  定义:调用一个对象的一个方法,以另一个对象替换当前对象。  说明:...
  • xuanjiewu
  • xuanjiewu
  • 2016年07月09日 22:57
  • 763

JavaScript中 apply/call 与面向对象语言中继承关系的联系和区别

apply是否可理解为类的继承?
  • sinat_27088253
  • sinat_27088253
  • 2016年10月24日 17:06
  • 615
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JavaScript closure: difference between call and apply as well as use them to create inheritance
举报原因:
原因补充:

(最多只允许输入30个字)