2017-04-23 106 views
2

我有点困惑学习所有新的ES6与ES5与JavaScript的语法,当涉及到方法和调用这些方法的函数/类时,我无法确切地告诉什么是“正确的方式”。Javascript this.function vs返回函数?

例如利用这个代码:

function account(amount) { 
    let cash = amount; 
    this.setCash = function(amt) 
    { 
    cash = amt; 
    } 
    this.getCash = function() 
    { 
    return cash; 
    } 
} 
var person = new account(100); 
console.log(person.getCash()); //returns 100 
person.setCash(150); 
console.log(person.getCash()); //returns 150 

作品像预期正常(这是我最初看到通过教程去时使用的方法)。

但是我已经看到了这个偶然:

function account2(amount) { 
    let cash = amount; 
    function setCash(amt) 
    { 
    cash = amt; 
    } 
    function getCash() 
    { 
    return cash; 
    } 
    return{ 
    getCash, 
    setCash 
    } 
} 
var person2 = new account2(50); 
console.log(person2.getCash()); //returns 50 
person2.setCash(175); 
console.log(person2.getCash()); //returns 175 

这两个完全正常工作,并且做的,因为我觉得他们应该。但是,只是一个更老的方法呢?或更少更正可能?这是我现在学习JS的最大障碍,因为ES6在这里有很多不同的方式来做一些简单的事情,比如在JS中用方法创建一个“类”。

就个人而言,第一种方式似乎更容易,因为您不必返回函数....但例如在工作中,我看到第二种方式主要用于?

+0

他们都不是年长者。他们同样“老”。没有一个是“更好”的,他们只是不同而已。选择一个适合你的案例。 – zerkms

+0

@zerkms有没有被认为是新“标准”的ES6方式? – msmith1114

+2

在JavaScript中没有任何单一的“标准”做任何事情。做任何适合**你**更好。 – zerkms

回答

3

如果您从第二个版本中删除了new(稍后会有更多内容),那么您的两个示例都是用私有数据通过公共get/set方法创建对象的完美方式。你会选择哪一个是个人喜好,还是取决于你是否想用原型方法进一步扩展功能等。

我建议从第二个版本中删除new的原因是虽然这两个示例都工作,但第一个一个“正常”使用the new operator,但第二个是“不正确”使用new操作符 - 不是语法错误,只是语义上不正确,并且可能会让其他人阅读您的代码时产生误导。

那么为什么第二次使用new的语义不正确呢?当你说var person = new account(100)

  1. 一个新的对象是创建与account.prototype的原型。这意味着新的对象继承了account.prototype的任何方法和属性,并从原型等。(在你的情况,你还没有定义在原型上的任何方法,但你能
  2. account()函数,this将引用在步骤1中创建的对象。这就是为什么您可以将方法附加到它的原因与this.setCash = ...
  3. 默认情况下,从account()返回新对象。如果有明确的return语句返回其他内容,如account2()函数中所示,则此步骤将发生而不是

所以在第一个例子中,person instanceof accounttrue,因为返回了默认对象。在第二个示例中,person2 instanceof account2false,因为返回了一个不同的对象 - 这会让人们读取代码时产生误导,因为当他们看到person2 = new account2()时,他们可能会合理地认为person2将是account2的实例,但事实并非如此。这也有点低效,因为JS引擎为你创建一个对象的麻烦,然后你不使用它。

所以第二个例子是更“正确”无new,提供相同的行为减去多余的自动创建对象:

var person2 = account2(50); 

(几乎)是你写任何JS函数可以被调用new,但有一个约定,我们描述函数打算作为“构造函数”调用new,通常函数名称是大写,所以Account(),而不是account()。 (拼写不会改变行为,它只是读取代码的人的额外暗示。)

请注意,使用new不是将对象链接到特定原型的唯一方式:它是旧式的 - 但仍是完全有效的方式,但您可以使用Object.create()来代替。

顺便说一句,有问题的行为是不是新的ES5或6,但let和快捷方式对象文字语法在account2新。

+0

快速问题,为什么person2 instanceof account2为false?我的意思是.... person2可以访问所有account2的功能?那为什么它不是它的一个实例呢?还是仅仅是它的副本? – msmith1114

+0

['instanceof' operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof)测试对象是否在其原型链中指定了指定的prototype属性构造函数。 'person2'可以访问的内容是不相关的,因为它具有不同的原型。它不是'account2'的副本。它可以访问这些函数,因为返回的对象具有对它们的引用。这些函数由于关闭而可以访问本地“现金”变量(这也是“账户”版本中的函数可以访问其“现金”变量的原因)。 – nnnnnn

+0

[闭包](https://developer.mozilla.org/en/docs/Web/JavaScript/Closures)和实例是两个独立的概念,尽管它们可以一起工作。 – nnnnnn

1

当您使用new创建实例时,隐式返回关键字this,因为在将函数分配给不带new的变量时,需要明确使用return