javascript:函数和类有什么区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11970141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 14:55:51  来源:igfitidea点击:

javascript: what's the difference between a function and a class

javascript

提问by Adam Lee

I am wondering what's the difference between function and class. Both using the keyword function, is there obvious distinction between those two?

我想知道函数和类之间有什么区别。两者都使用关键字function,这两者之间有明显的区别吗?

回答by Esailija

There is technically no class, they're both just functions. Any function can be invoked as a constructor with the keyword newand the prototype property of that function is used for the object to inherit methods from.

技术上没有类,它们都只是函数。任何函数都可以作为带有关键字的构造函数调用,new并且该函数的原型属性用于对象继承方法。

"Class" is only used conceptually to describe the above practice.

“类”仅在概念上用于描述上述实践。

So when someone says to you "make a color class" or whatever, you would do:

因此,当有人对您说“制作颜色课程”或其他任何内容时,您会这样做:

function Color(r, g, b) {
    this.r = r;
    this.g = g;
    this.b = b;
}

Color.prototype.method1 = function() {

};

Color.prototype.method2 = function() {

};

When you break it down, there is simply a function and some assignments to a property called prototypeof that function, all generic javascript syntax, nothing fancy going on.

当你分解它时,只有一个函数和一些prototype对该函数调用的属性的赋值,所有通用的javascript语法,没有什么花哨的。

It all becomes slightly magical when you say var black = new Color(0,0,0). You would then get an object with properties .r, .gand .b. That object will also have a hidden [[prototype]] link to Color.prototype. Which means you can say black.method1()even though .method1()does not exist in the blackobject.

当你说的时候,这一切都变得有点神奇var black = new Color(0,0,0)。然后您将获得一个具有属性.r,.g和的对象.b。该对象还将有一个隐藏的 [[prototype]] 链接到Color.prototype. 这意味着您可以说black.method1()即使.method1()不存在于black对象中。

回答by Yash

JavaScriptis the most popular implementation of the ECMAScript Standard. The core features of Javascript are based on the ECMAScript standard, but Javascript also has other additional features that are not in the ECMA specifications/standard. Every browser has a JavaScript interpreter.

JavaScript是 ECMAScript 标准最流行的实现。Javascript 的核心功能基于 ECMAScript 标准,但 Javascript 还具有 ECMA 规范/标准中没有的其他附加功能。每个浏览器都有一个 JavaScript 解释器。



Overview

Overview

?ECMAScript was originally designed to be a Web scripting language, providing a mechanism to enliven Web pages in browsers and to perform server computation as part of a Web-based client-server architecture. A scripting language is a programming language that is used to manipulate, customize, and automate the facilities of an existing system.

? ECMAScript 最初被设计为一种 Web 脚本语言,提供一种机制来活跃浏览器中的网页并作为基于 Web 的客户端-服务器架构的一部分执行服务器计算。脚本语言是一种编程语言,用于操作、定制和自动化现有系统的设施。

ECMAScript is an object-oriented programming language for performing computations and manipulating computational objects within a host environment. A web browser provides an ECMAScript host environment for client-side computation including, for instance, objects that represent windows, menus, pop-ups, dialog boxes, text areas, anchors, frames, history, cookies, and input/output.

ECMAScript 是一种面向对象的编程语言,用于在宿主环境中执行计算和操作计算对象。Web 浏览器为客户端计算提供了一个 ECMAScript 宿主环境,包括例如代表窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史记录、cookie 和输入/输出的对象。

ECMAScript is object-based: basic language and host facilities are provided by objects, and an ECMAScript program is a cluster of communicating objects

ECMAScript 是基于对象的:基本语言和宿主设施由对象提供,ECMAScript 程序是一组通信对象

Objects ?

对象?

  • Each constructor is a function that has a property named “prototype”that is used to implement prototype-based inheritance and shared properties.

  • Every object created by a constructor has an implicit reference (called the object's prototype) to the value of its constructor's “prototype”property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain.

  • 每个构造函数都是一个函数,它有一个名为的属性“prototype”,用于实现基于原型的继承和共享属性。

  • 构造函数创建的每个对象都有一个对其constructor's “prototype”属性值的隐式引用(称为对象的原型)。此外,原型可能具有对其原型的非空隐式引用,依此类推;这称为prototype chain.



Function

功能

JavaScript treats functions as first-class objects, so being an object, you can assign properties to a function.

JavaScript 将函数视为一等对象,因此作为对象,您可以为函数分配属性。

Hoisting is the JavaScript interpreter's action of moving all variable and function declarations to the top of the current scope. Function Hoisting, declarations & expressions

提升是 JavaScript 解释器将所有变量和函数声明移动到当前作用域顶部的动作。 Function Hoisting, declarations & expressions

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }

FunctionDeclaration:函数BindingIdentifier(FormalParameters){FunctionBody}FunctionExpression:函数BindingIdentifier(FormalParameters){FunctionBody}

ES5 Function:

ES5 功能:

function Shape(id) { // Function Declaration
    this.id = id;
};
// prototype was created automatically when we declared the function
Shape.hasOwnProperty('prototype'); // true

// Adding a prototyped method to a function.
Shape.prototype.getID = function () {
    return this.id;
};

var expFn = Shape; // Function Expression
console.dir( expFn () ); // Function Executes and return default return type - 'undefined'

To a function if the return value is not specified, then undefinedis returned.If the function is invoked with newand the return value is not an object, then this (the new object) is returned.

如果未指定返回值,则undefined返回给函数。如果函数被调用new并且返回值不是对象,则返回 this(新对象)。

NOTE: A prototype property is automatically created for every function, to allow for the possibility that the function will be used as a constructor.

  • constructor? Function object that creates and initializes objects.
  • prototype? object that provides shared properties for other objects.
  • __proto__? The protoproperty which points to its super object's prototype. If you open it up you will see that protopoints to its super object variables and functions.

注意:为每个函数自动创建一个原型属性,以允许将函数用作构造函数的可能性。

  • constructor? 创建和初始化对象的函数对象。
  • prototype? 为其他对象提供共享属性的对象。
  • __proto__? 在财产分给其超强的对象的原型。如果你打开它,你会看到proto指向它的超级对象变量和函数。

To access prototype methods of above crated function, we need to create object using newkeyword along with constructor function. if you are creating Shape - Objectusing newkeyword then it has an internal (or) private linkto function's prototype Shape.

要访问上述 crated 函数的原型方法,我们需要使用new关键字和constructor function. 如果您正在创建Shape - Objectusingnew关键字,那么它有一个internal (or) private linkto 函数的原型Shape

ES5 Constructor Function Classes: Function objects created using Function.prototype.bind

ES5 构造函数类:使用 Function.prototype.bind 创建的函数对象

Shape.prototype.setID = function ( id ) {
    this.id = id;
};

var funObj = new Shape( );
funObj.hasOwnProperty('prototype'); // false
funObj.setID( 10 )
console.dir( funObj );

console.log( funObj.getID() );
/*
expFun                            funObj
    name: "Shape"                   id: 10
    prototype:Object
        constructor: function Shape(id)
        getID: function()
        setID: function( id )
    __proto__: function ()          __proto__: Object
                                        constructor: function Shape(id)
                                        getID: function()
                                        setID: function( id )
    <function scope>
*/

ES6 introduced Arrow function: An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors. ArrowFunction grammar production do not have a prototype property.

ES6 引入了箭头函数箭头函数表达式的语法比函数表达式更短,并且不绑定自己的 this、arguments、super 或 new.target。这些函数表达式最适合非方法函数,它们不能用作构造函数。ArrowFunction 语法产生式没有原型属性。

ArrowFunction : ArrowParameters => ConciseBody

  a => (a < 10) ? 'valid' : 'invalid'

  const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; };
    console.log( fn(2) ); // Even
    console.log( fn(3) ); // Odd

ArrowFunction : ArrowParameters => ConciseBody

  a => (a < 10) ? 'valid' : 'invalid'

  const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; };
    console.log( fn(2) ); // Even
    console.log( fn(3) ); // Odd


Class

班级

In a class-based object-oriented language, in general, state is carried by instances, methods are carried by classes, and inheritance is only of structure and behavior. In ECMAScript, the state and methods are carried by objects, and structure, behavior, and state are all inherited.

在基于类的面向对象语言中,一般情况下,状态由实例承载,方法由类承载,继承只有结构和行为。在 ECMAScript 中,状态和方法由对象承载,结构、行为和状态都是继承的。

Babel is a JavaScript compiler. Use it to Transform ES6to ES5format BABEL JS(or) ES6Console.

Babel 是一个 JavaScript 编译器。用它转换ES6ES5格式化BABEL JS(或)ES6Console

ES6 Classes: ES2015 classesare a simple sugar over the prototype-based OO pattern. Having a single convenient declarative form makes class patterns easier to use, and encourages interoperability. Classes support prototype-based inheritance, super calls, instance and static methods and constructors.

ES6 类ES2015 classes是基于原型的 OO 模式的简单糖。拥有一个方便的声明形式使类模式更易于使用,并鼓励互操作性。类支持基于原型的继承、超级调用、实例和静态方法和构造函数。

class Shape {
  constructor(id) {
    this.id = id
  }

  get uniqueID() {
    return this.id;
  }
  set uniqueID(changeVal) {
    this.id = changeVal;
  }
}
Shape.parent_S_V = 777;

// Class Inheritance
class Rectangle extends Shape {

  constructor(id, width, height) {
    super(id)
    this.width = width
    this.height = height
  }
  // Duplicate constructor in the same class are not allowed.
  /*constructor (width, height) { this._width  = width; this._height = height; }*/

  get area() {
    console.log('Area : ', this.width * this.height);
    return this.width * this.height
  }
  get globalValue() {
    console.log('GET ID : ', Rectangle._staticVar);
    return Rectangle._staticVar;
  }
  set globalValue(value) {
    Rectangle._staticVar = value;
    console.log('SET ID : ', Rectangle._staticVar);
  }

  static println() {
    console.log('Static Method');
  }

  // this.constructor.parent_S_V - Static property can be accessed by it's instances
  setStaticVar(staticVal) { // https://sckoverflow.com/a/42853205/5081877
    Rectangle.parent_S_V = staticVal;
    console.log('SET Instance Method Parent Class Static Value : ', Rectangle.parent_S_V);
  }

  getStaticVar() {
    console.log('GET Instance Method Parent Class Static Value : ', Rectangle.parent_S_V);
    return Rectangle.parent_S_V;
  }
}
Rectangle._staticVar = 77777;

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir( objTest );

ES5 Function Classes: uses Object.defineProperty ( O, P, Attributes )

ES5 函数类:用途Object.defineProperty ( O, P, Attributes )

The Object.defineProperty()method defines a new property directly on an object, or modifies an existing property on an object, and returns the object.

Function instances that can be used as a constructor have a prototype property.

This property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }.

Object.defineProperty()方法直接在对象上定义新属性,或修改对象上的现有属性,并返回该对象。

可用作构造函数的函数实例具有原型属性

此属性具有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

    'use strict';
var Shape = function ( superClass ) {
    var currentClass = Shape;
    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Shape(id) { superClass.call(this); // Linking with SuperClass Constructor.
        // Instance Variables list.
        this.id = id;   return this;
    }
    var staticVariablesJOSN = { "parent_S_V" : 777 };
    staticVariable( currentClass, staticVariablesJOSN );

    // Setters, Getters, instanceMethods. [{}, {}];
    var instanceFunctions = [
        {
            key: 'uniqueID',
            get: function get() { return this.id; },
            set: function set(changeVal) { this.id = changeVal; }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Object);

var Rectangle = function ( superClass ) {
    var currentClass = Rectangle;

    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Rectangle(id, width, height) { superClass.call(this, id); // Linking with SuperClass Constructor.

        this.width = width;
        this.height = height;   return this;
    }

    var staticVariablesJOSN = { "_staticVar" : 77777 };
    staticVariable( currentClass, staticVariablesJOSN );

    var staticFunctions = [
        {
            key: 'println',
            value: function println() { console.log('Static Method'); }
        }
    ];
    staticMethods(currentClass, staticFunctions);

    var instanceFunctions = [
        {
            key: 'setStaticVar',
            value: function setStaticVar(staticVal) {
                currentClass.parent_S_V = staticVal;
                console.log('SET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
            }
        }, {
            key: 'getStaticVar',
            value: function getStaticVar() {
                console.log('GET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
                return currentClass.parent_S_V;
            }
        }, {
            key: 'area',
            get: function get() {
                console.log('Area : ', this.width * this.height);
                return this.width * this.height;
                }
        }, {
            key: 'globalValue',
            get: function get() {
                console.log('GET ID : ', currentClass._staticVar);
                return currentClass._staticVar;
            },
            set: function set(value) {
                currentClass._staticVar = value;
                console.log('SET ID : ', currentClass._staticVar);
            }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Shape);

// ===== ES5 Class Conversion Supported Functions =====
function defineProperties(target, props) {
    console.log(target, ' : ', props);
    for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function staticMethods( currentClass, staticProps ) {
    defineProperties(currentClass, staticProps);
};
function instanceMethods( currentClass, protoProps ) {
    defineProperties(currentClass.prototype, protoProps);
};
function staticVariable( currentClass, staticVariales ) {
    // Get Key Set and get its corresponding value.
    // currentClass.key = value;
    for( var prop in staticVariales ) {
        console.log('Keys : Values');
        if( staticVariales.hasOwnProperty( prop ) ) {
            console.log(prop, ' : ', staticVariales[ prop ] );
            currentClass[ prop ] = staticVariales[ prop ];
        }
    }
};
function _inherits(subClass, superClass) {
    console.log( subClass, ' : extends : ', superClass );
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, 
            { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
    if (superClass)
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir(objTest);

Below code snippet is to test about Each instance has their own copy of instance members and common static members.

下面的代码片段是为了测试每个实例都有自己的实例成员和公共静态成员的副本。

var obj1 = new Rectangle('R_1', 50, 20);
Rectangle.println(); // Static Method
console.log( obj1 );    // Rectangle {id: "R_1", width: 50, height: 20}
obj1.area;              // Area :  1000
obj1.globalValue;       // GET ID :  77777
obj1.globalValue = 88;  // SET ID :  88
obj1.globalValue;       // GET ID :  88  

var obj2 = new Rectangle('R_2', 5, 70);
console.log( obj2 );    // Rectangle {id: "R_2", width: 5, height: 70}
obj2.area;              // Area :  350    
obj2.globalValue;       // GET ID :  88
obj2.globalValue = 999; // SET ID :  999
obj2.globalValue;       // GET ID :  999

console.log('Static Variable Actions.');
obj1.globalValue;        // GET ID :  999

console.log('Parent Class Static variables');
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  777
obj1.setStaticVar(7);   // SET Instance Method Parent Class Static Value :  7
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  7



Major Differences between functions and classes are:

  • Function Declarations get Hoistedto Top of the context, where as classes declarations and function Expressions are not Hoisted.
  • Function Declarations, Expression can be Overriddenas they are like a Variable - varif multiple declaration are available then it overrides its parent scope. Where as the Classes are not Overridden they are like let| const, let doesn't allows multiple declaration with same name inside its scope.
  • Function's / classes allows only single constructor for its object scope.
  • Computed method namesare allowed to ES6 classes having class keyword, but function keyword is not allows it

    function myFoo() {
     this.['my'+'Method'] = function () { console.log('Computed Function Method'); };
    }
    class Foo {
        ['my'+'Method']() { console.log('Computed Method'); }
    }
    

函数和类之间的主要区别是:

  • 函数声明到达Hoisted上下文的顶部,因为类声明和函数表达式没有被提升。
  • 函数声明,表达式可以Overridden像变量一样 -如果有多个声明可用,则它会覆盖其父作用域。当类没有被覆盖时,它们就像| , let 不允许在其作用域内有多个同名声明。varletconst
  • 函数的 / 类只允许为其对象范围使用单个构造函数。
  • Computed method names允许具有 class 关键字的 ES6 类,但不允许使用 function 关键字

    function myFoo() {
     this.['my'+'Method'] = function () { console.log('Computed Function Method'); };
    }
    class Foo {
        ['my'+'Method']() { console.log('Computed Method'); }
    }
    

回答by jbabey

In javascript, there are no classes. javascript uses prototype inheritance rather than class based inheritance. Many people will refer to classes in javascript because it is easier to understand, but it is purely an analogy.

在 javascript 中,没有类。javascript 使用原型继承而不是基于类的继承。很多人会提到javascript中的类,因为它更容易理解,但这纯粹是一个类比。

In class based inheritance, you create a class (a "blueprint", if you will) and then instantiate objects from that class.

在基于类的继承中,您创建一个类(一个“蓝图”,如果您愿意的话),然后从该类实例化对象。

In prototype inheritance, an object is instantiated directly from another parent object, without ever needing any "blueprints".

在原型继承中,一个对象直接从另一个父对象实例化,不需要任何“蓝图”。

See the wikipedia pagefor more information on Class vs Prototype inheritance.

有关类与原型继承的更多信息,请参阅维基百科页面

回答by Willem van der Veen

Difference between a (constructor) functionand class

a(构造函数)functionclass

The classkeyword in javascript is merely syntactical sugar for a constructor function which still is using javascript's prototyping system. The only 'difference' that is present is the syntax, under the hood they are the same.

classjavascript 中的关键字只是构造函数的语法糖,该函数仍在使用 javascript 的原型系统。唯一存在的“差异”是语法,在本质上它们是相同的。

An example should clarify this:

一个例子应该澄清这一点:

class PersonClass {
  constructor(name) {
    this.name = name;
  }
  
  speak () { console.log('hi'); }
}

console.log(typeof PersonClass); 
// logs function, a class is a constructor function under the hood.

console.log(PersonClass.prototype.speak);
// The class's methods are placed on the prototype of the PersonClass constructor function

const me = new PersonClass('Willem');

console.log(me.name); 
// logs Willem, properties assinged in the constructor are placed on the newly created object


// The constructor function equivalent would be the following:
function PersonFunction (name) {
  this.name = name;
}

PersonFunction.prototype.speak = function () { console.log('hi'); }

回答by Samuel

The term classis usually used in an object-oriented programming language context. A class is a template of the object that will be created at instantiation. JavaScript is a prototype-based programming language, therefore it's a little strange to use the term class to describe a JavaScript prototype. In JavaScript prototypes are created as functions

术语通常用于面向对象的编程语言上下文中。类是将在实例化时创建的对象的模板。JavaScript 是一种基于原型的编程语言,因此使用术语类来描述 JavaScript 原型有点奇怪。在 JavaScript 中,原型被创建为函数

回答by hyang123

One key distinction between functions and classes was highlighted in this talkwhich suggests that a function a behavior that can carry data while, inversely, a class is data that can carry behavior.

本次演讲强调了函数和类之间的一个关键区别,这表明函数是一种可以携带数据的行为,而相反,类是可以携带行为的数据。

回答by Srikrushna

Class

班级

A class declaration is scoped to its containing block. It is an error to declare a class name twice in the same block. Class definition are not hoisted.

类声明的范围是它的包含块。在同一个块中两次声明一个类名是错误的。类定义没有被提升。

Functions

职能

Function declaration is block scope in strict mode.

函数声明在严格模式下是块作用域。

The below table summarize the difference between class and function enter image description here

下表总结了类和函数之间的区别 在此处输入图片说明