简体   繁体   English

在函数内部调用函数

[英]Calling function inside of function

When I code stuff, I try to divide all things in functions (methods, if you like). 当我编写代码时,我会尝试将所有事物划分为函数(方法,如果您愿意的话)。 Function X does stuff X, Y does tuff Y and not like method X does stuff X, Y & Z! 函数X填充X,Y填充Y, 不像方法X填充X,Y和Z! This gives me more re-usable code. 这给了我更多可重用的代码。 I like that. 我喜欢。 :) :)

Lets take a look on this code: 让我们看一下这段代码:

var user = {
  users: [],
  userCount: 0,
  addUser: function(user) {
    (this.users).push(user);
  },
  incrementCount: function() {
    ++this.userCount;
  }
}

var user = { // 2nd example.
  users: [],
  userCount: 0,
  addUser: function(user) {
    (this.users).push(user);
    ++this.userCount;
  }
}

(It's in JavaScript, but language here is non-essential.) (它使用JavaScript,但是此处的语言不是必需的。)

In my opinion, second example will be easier and safer to use for, lets say, API user. 我认为,第二个示例对于API用户来说将更容易使用,也更安全 It's easy to forget to call user.incrementCount() . 忘记调用user.incrementCount()很容易。 What do you think? 你怎么看? Second example does it automatically. 第二个示例自动执行。

So how to find a balance? 那么如何找到平衡呢? Any best-practices about calling functions inside of functions? 关于在函数内部调用函数的最佳做法?

Thanks for reading this. 感谢您阅读本文。

Edit : 编辑

This came in my mind just now: 刚才我想到了这一点:

var user = {
  users: [],
  userCount: 0,
  addUser: function(user) {
    (this.users).push(user);
    this.incrementCount();
  },
  incrementCount: function() {
    ++this.userCount;
  }
}

It's a little different in JS, since there isn't a way to make functions truly private when using object literal notation, but... 在JS中有所不同,因为在使用对象文字表示法时,没有一种方法可以使函数真正私有, 但是...

It's all about the API you want your objects to expose to their consumers. 这与您希望对象向其使用者公开的API有关。 Do you want consumers of your API to be able to increment the count separately from adding a user? 您是否希望API的使用者能够独立于增加用户而增加计数? If so: 如果是这样的话:

{ addUser: /* snip */, incrementCount: /* snip */ }

Otherwise: 除此以外:

{ addUser: /* snip */, _incrementCount: /* snip */ }
// or just
{ addUser: /* snip */ }

In this particular case, I would strongly recommend against storing any separate count at all, since the users array already does that for you. 在这种情况下,我强烈建议不要存储任何单独的计数,因为users数组已经为您完成了。

var user = {
  _users: [],
  addUser: function(user) {
      this._users.push(user);
  },
  getUserCount: function () {
      return this._users.length;
  }
  // and if you need to expose the users array directly,
  , getUsers: function () {
      return this._users;
  }
}

Personally, I don't think you should even expose that stuff through an API. 就个人而言,我什至不建议您通过API公开这些内容。 Also, it would be easier and (at least in JavaScript) more intuitive, to just use users.length . 而且,仅使用users.length会更容易并且(至少在JavaScript中)更直观。

Ultimately, I think keeping your interface really simple is generally a good thing. 最终,我认为保持界面非常简单通常是一件好事。 Abstraction is a good thing. 抽象是一件好事。 If I were using someone else's library, I'd be pretty disappointed to learn that I was expected to manually increment that value. 如果我使用的是其他人的库,得知我希望手动增加该值会感到非常失望。

Update: 更新:

One more thing I think is worth mentioning: 我认为还有一件事值得一提:

By having your code maintain state internally and keeping the API simple, you not only make the user's life easier, but you also protect against misuse (to the extent that it's possible). 通过使代码在内部维护状态并保持API简单,不仅可以简化用户的生活,而且还可以防止滥用(在可能的范围内)。 It's easy to imagine a scenario where someone uses that increment method incorrectly, and as a result, it's going to break stuff. 容易想象一个场景,有人不正确地使用该增量方法,结果将破坏东西。

You are right in saying "Function A does A-Stuff." 您说对了,“函数A做A-材料”是对的。 BUT: a function that works on data, that is hidden (more or less) from the outside, should do stuff you want with the data (for Example add a User) and makes shure, that the data still is correct (for example if you have a list of users, increment the Usercounter to make make shure it is always correct). 但是:一种对数据起作用的函数,该函数从外部隐藏(或多或少),应该对数据进行所需的处理(例如,添加用户),并确保数据仍然正确(例如,如果您有一个用户列表,请增加Usercounter使其始终正确)。 If you leave want the user of your API do this stuff for you, it is not comfortable anyways. 如果您想让您的API用户为您做这些事情,那还是很不舒服的。

Imagine, you add more functionality to your list of users (for example, tell the user that it has been added to the list, store the Users in a binary tree and so on), and you have to do all the organisation stuff from the outside of your function, where are the benefits of that?? 想象一下,您向用户列表中添加了更多功能(例如,告诉用户已将其添加到列表中,将用户存储在二叉树中,依此类推),并且您必须从在您的功能之外,这样做的好处是什么?

I know you've just intended the sample code to be a simple example, but with something like a count or length variable I can't think of a reason why I'd ever want to let that be set independent of the function(s) that add or remove items. 我知道您只是想将示例代码作为一个简单的示例,但是对于诸如count或length变量之类的东西,我想不出为什么我想让其独立于函数进行设置的原因)添加或删除项目。 When using the object you don't want to have to call an add() and an increment() method every time you add, and you really don't want to be able to do one without the other or your object ends up in an invalid state. 使用该对象时,您不需要每次add()都必须调用add() increment()方法,并且您确实不希望在没有其他对象的情况下执行一个操作,否则您的对象最终会陷入无效状态。

So I'd never do it the first way, and surely the way you added in your edit is even worse. 因此,我永远不会做第一种方法,当然,您在编辑中添加的方法肯定会更糟。 There's nothing wrong with having your functions call each other, but again in your example I'd want the increment function to be private. 让您的函数相互调用没有错,但是在您的示例中,我还是希望增量函数是私有的。

Better to make the count variable private and only allow it to be retrieved via a function and set via add/remove functions (though you don't even need a count variable when you can just return users.length ). 最好将count变量设为私有,并且只允许通过函数检索并通过add / remove函数进行设置(尽管当您只需要返回users.length时,甚至不需要count变量)。 The following pattern with an immediately executed anonymous function lets you have private variables and functions, and you only return an object containing public functions. 带有立即执行的匿名函数的以下模式使您可以拥有私有变量和函数,并且仅返回包含公共函数的对象。 The public functions can still access the private variables/functions, but the private stuff can't be accessed from outside. 公共函数仍然可以访问私有变量/函数,但是私有内容不能从外部访问。

var user = (function() {
   var users = [],    // private variables
       private1,
       private2;

   function privateFunction1() { /* do something */ }

   return {
      getUserCount : function() {
                       return users.length;
                     },
      addUser:       function(user) {
                       users.push(user);
                       // return index of new user
                       return users.length - 1;
                     },
      getUser :      function(userIndex) {
                       return users[userIndex];
                     },
      someFunc :     function(someParam) {
                       return someParam + privateFunction1();
                     }
   }
})();

user.addUser("Fred");
user.addUser("Mary");
console.log(user.getUserCount()); // 2
console.log(user.getUser(1));     // Mary

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM