javascript:函数和类之间的区别是什么

Ada*_*Lee 18 javascript

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

Esa*_*ija 23

技术上没有课,它们都只是功能.任何函数都可以作为带有关键字的构造函数调用,该函数new的prototype属性用于从中继承方法的对象.

"类"仅用于概念性地描述上述实践.

所以当有人对你说"制作颜色课"或其他什么时,你会这样做:

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

Color.prototype.method1 = function() {

};

Color.prototype.method2 = function() {

};
Run Code Online (Sandbox Code Playgroud)

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

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

  • @Harsha在ES6中添加了类语法。它们仍然在下面起作用。 (3认同)
  • **全部**:请注意,这个答案现在已经过时了。发布三年后,ES2015 在 JavaScript 中添加了“class”语法。查看此后发布的其他答案。 (3认同)

Yas*_*ash 9

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


Overview

« ECMAScript最初设计为Web脚本语言,提供了一种机制,可以在浏览器中使网页活跃起来,并作为基于Web的客户端 - 服务器体系结构的一部分执行服务器计算.脚本语言是一种编程语言,用于操作,定制和自动化现有系统的功能.

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

ECMAScript是基于对象的:基础语言和主机设施由对象提供,ECMAScript程序是通信对象的集群

物品«

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

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


功能

JavaScript将函数视为第一类对象,因此作为对象,您可以为函数指定属性.

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

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

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'
Run Code Online (Sandbox Code Playgroud)

如果未指定返回值,则undefined返回函数,然后返回. 如果调用函数new并且返回值不是对象,则返回此(新对象).

注意:为每个函数自动创建一个prototype属性,以允许该函数用作构造函数.

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

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

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>
*/
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

在基于类的面向对象语言中,通常,状态由实例承载,方法由类承载,而继承仅由结构和行为承载.在ECMAScript中,状态和方法由对象承载,结构,行为和状态都是继承的.

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

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 );
Run Code Online (Sandbox Code Playgroud)

ES5功能类:用途Object.defineProperty ( O, P, Attributes )

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

可用作构造函数的函数实例具有prototype属性.

此属性具有{[[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);
Run Code Online (Sandbox Code Playgroud)

下面的代码片段是测试每个实例都有自己的实例成员和常用静态成员的副本.

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
Run Code Online (Sandbox Code Playgroud)


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

  • 函数声明到达Hoisted上下文的顶部,其中类声明和函数表达式未被提升.
  • 函数声明,表达式可以Overridden像变量一样 - 如果有多个声明可用,那么它将覆盖其父作用域.如果没有重写类,它们就像| ,let不允许在其范围内使用同名的多个声明.var letconst
  • 函数/类只允许单个构造函数用于其对象作用域.
  • Computed method names 允许带有class关键字的ES6类,但函数关键字不允许它

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


jba*_*bey 7

在javascript中,没有任何类。javascript使用原型继承而不是基于类的继承。许多人会使用javascript来引用类,因为它更易于理解,但纯粹是一个类比。

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

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

有关类与原型继承的更多信息,请参见Wikipedia页面


Wil*_*een 6

构造函数function和构造函数之间的区别class

javascript 中的关键字class与构造函数非常相似,如下所示:

  • 他们都使用 javascript 的原型继承系统
  • 它们都用于使用以下语法创建对象:new myObj(arg1, arg2)

构造函数和类非常相似,通常可以根据偏好互换使用。然而,javascript 类的私有字段是无法通过构造函数实现的功能(没有作用域 hack)

例子:

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'); }
Run Code Online (Sandbox Code Playgroud)