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

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

相关文章推荐

Michael Kors Laukut dope need and as well lung cancer: connection between a suit operate education

cannabis employ with united states: outcomes of in a situation decrease survey. us citizen Thoracic ...

how to use a SQLite database in a standalone program with an HTML interface and VBScript as the programming language

This article describes how to use a SQLite database in a standalone program with an HTML interface a...

Difference Between CALL TRANSACTION and SESSION METHOD

for this subject, I got 2 articles for reference: 1. http://wiki.sdn.sap.com/wiki/display/ABAP/Diff...

AS3 中,Function.apply、call中第一个参数的作用;与什么时候用;

大家在使用Function.apply或是call时,是否发现,第一个参数不知道怎么用,赋值了也没反应; 没反应的情况,是因为你的这个Function是普通的类成员函数; 看apply,call的...

as3.0 Function.apply()与Function.call()方法简介

Function:函数是可在 ActionScript 中调用的基本代码单位。 ActionScript 中用户定义的函数和内置函数都由 Function 对象来表示,该对象是 Function 类的...

Difference between prototype and this in JavaScript

When I’m studying JavaScript, I got a little bit confused while I first time look at function.protot...

A Guide to Blocks & Grand Central Dispatch (and the Cocoa API's making use of them)

Intro As you may or may not know I recently did a talk at the Des Moines Cocoaheads in which I revie...

Swift Optionals: When to use if let, when ? and !, when as? and as

原文地址:http://www.touch-code-magazine.com/swift-optionals-use-let/1. 可选类型是什么?回忆你知道的普通的数据类型,就像你在的Object...

How to use json with as3corelib in flex( JSON )

How to use json with as3corelib in flex(  JSON ) 摘要:本文主要介绍as3corelib如何在flex中使用,以及如何在flex中使用json...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JavaScript closure: difference between call and apply as well as use them to create inheritance
举报原因:
原因补充:

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