每个Node.js开发人员必须掌握的10个JavaScript概念

Rahul Mhatre是Software AG的开发团队负责人。

以JavaScript和V8引擎为核心,具有事件驱动的体系结构和开箱即用的可扩展性,Node.jsSwift成为创建Web应用程序和SaaS产品的事实上的标准。 诸如Express,Sails和Socket.IO之类的Node.js框架允许用户快速引导应用程序,并仅关注业务逻辑。

Node.js得益于JavaScript的巨大普及。 JavaScript是一种多范式语言,支持许多不同样式的编程,包括函数式编程,过程式编程和面向对象的编程。 它使开发人员可以变得灵活,并可以利用各种编程风格。

[也在InfoWorld上: 6个最佳JavaScript IDE10个最佳JavaScript编辑器 | 通过InfoWorld的App Dev Report新闻通讯了解编程方面的热门话题。 ]

但是JavaScript可能是一把双刃剑。 JavaScript的多范式性质意味着几乎所有内容都是可变的。 因此,在编写Node.js代码时,您不能忽略对象和作用域发生突变的可能性。 因为JavaScript缺少尾部调用优化(允许递归函数将堆栈框架重用于递归调用),所以对大迭代使用递归是危险的。 除了这些陷阱之外,Node.js是单线程的,因此开发人员必须编写异步代码。

如果谨慎使用,JavaScript可能会带来好处;如果您不计后果,JavaScript可能会有所帮助。 遵循结构化规则,设计模式,关键概念和基本经验法则将帮助您选择解决问题的最佳方法。 Node.js程序员应该了解哪些关键概念? 下面,我将分享我认为对编写高效且可扩展的Node.js代码至关重要的10个JavaScript概念。

相关视频:Node.js技巧和窍门

在此讲解视频中,学习一些可以改善Node开发体验的技术。

JavaScript IIFE:立即调用函数表达式

立即调用的函数表达式(IIFE)是创建后立即执行的函数。 它与任何事件或异步执行都没有关系。 您可以定义一个IIFE,如下所示:

(function() {
// all your code here
// ...
})();

第一对括号function(){...}将括号内的代码转换为表达式。第二对括号调用由表达式产生的函数。 IIFE也可以描述为自调用匿名函数。 它最常见的用法是限制通过var生成的变量的范围,或者封装上下文以避免名称冲突。

JavaScript闭包

JavaScript中的闭包是一个内部函数,即使该外部函数返回了控制,它也可以访问其外部函数的作用域。 闭包将内部函数的变量设为私有。 一个关闭的简单示例如下所示:

var count = (function () {
    var _counter = 0;
    return function () {return _counter += 1;}
})();

count();
count();
count();

>// the counter is now 3

变量count分配有外部功能。 外部函数仅运行一次,这会将计数器设置为零并返回内部函数。 _counter变量只能由内部函数访问,这使其行为类似于私有变量。

JavaScript原型

每个JavaScript函数都有一个原型属性,用于附加属性和方法。 此属性不可枚举。 它允许开发人员将方法或成员函数附加到其对象。 JavaScript仅通过prototype属性支持继承。 对于继承的对象,prototype属性指向该对象的父对象。 将方法附加到函数的常见方法是使用原型,如下所示:

function Rectangle(x, y) {
    this._length = x;
    this._breadth = y;
}

Rectangle.prototype.getDimensions = function () {
    return { length : this._length, breadth : this._breadth };
};

Rectangle.prototype.setDimensions = function (len, bred) {
    this._length = len;
    this._breadth = bred;
};

JavaScript私有属性,使用闭包

JavaScript使您可以使用下划线前缀来定义私有属性,如上例所示。 但是,这不会阻止用户直接访问或修改应该是私有的属性。

使用闭包定义私有属性将帮助您解决此问题。 需要访问私有属性的成员函数应该在对象本身上定义。 您可以使用闭包来制作私有属性,如下所示:

function Rectangle(_length, _breadth) {

     this.getDimensions = function () {
     return { length : _length, breadth : _breadth };
     };

     this.setDimension = function (len,bred) {
     _length = len;
    _breadth = bred
    };

}

JavaScript模块模式

模块模式是JavaScript中最常用的设计模式,用于实现松散耦合的结构良好的代码。 它允许您创建公共和私有访问级别。 实现模块模式的一种方法如下所示:

var Direction = (function() {
  var _direction = 'forward'
  var changeDirection = function(d) {
          _direction = d;
  }

  return {           setDirection: function(d) {
          changeDirection(d);
          console.log(_direction);
          }
  };

})();

Direction.setDirection('backward');   // Outputs: 'backward'
console.log(Direction._direction);

Revealing Module模式类似于Module模式,其中需要公开的变量和方法以对象文字形式返回。 可以使用“显示模块”模式来编写以上示例,如下所示:

var Direction = (function() {
  var _direction = 'forward';
  var _privateChangeDirection = function(d) {
_direction = d;
  }

  return {
          setDirection: _privateChangeDirection
  };

})();

JavaScript吊装

JavaScript在代码执行之前将变量和函数声明移至其作用域的顶部。 这称为吊装。 无论将函数和变量的声明放在代码中的何处,解释器都会将它们声明到其作用域的顶部。 这可能是您想要的地方,也可能不是。 如果不是,则您的程序将有错误。

在执行任何代码之前,先处理变量声明。 具有讽刺意味的是,未声明的变量在被赋值之前是不存在的。 这将导致所有未声明的变量成为全局变量。 尽管函数声明被悬挂,但函数表达式未被悬挂。 在提升变量和函数时,JavaScript具有优先级。

下面从高到低给出了优先级:

  • 变量分配
  • 功能声明
  • 变量声明

为避免错误,应在每个作用域的开头声明变量和函数。

JavaScript currying

咖喱是使功能更灵活的一种方法。 使用curried函数,您可以传递该函数期望的所有参数并获得结果,也可以仅传递参数的一个子集并接收返回的函数,以等待其余的参数。 下面是一个简单的咖喱示例:

var myFirstCurry = function(word) {
  return function(user) {
            return [word , ", " , user].join("");
  };
};

var HelloUser = myFirstCurry("Hello");
HelloUser("Rahul"); // Output: "Hello, Rahul"

可以通过以下方式直接调用原始的curried函数:将每个参数放在一个单独的括号内,如下所示:

myFirstCurry("Hey, wassup!")("Rahul"); // Output: "Hey, wassup!, Rahul"

JavaScript应用,调用和绑定方法

任何JavaScript开发人员都必须了解callapplybind方法之间的区别。 这三个函数的相似之处在于,它们的第一个参数始终是您要为其提供调用方法的函数的“ this”值或上下文。

在这三个中, call是最简单的。 这与在指定函数上下文时调用函数相同。 这是一个例子:

var user = {
     name: "Rahul Mhatre",
     whatIsYourName: function() {
     console.log(this.name);
     }
};

user.whatIsYourName(); // Output: "Rahul Mhatre",
var user2 = {
     name: "Neha Sampat"
};

user.whatIsYourName.call(user2); // Output: "Neha Sampat"

请注意, applycall几乎相同。 唯一的区别是您将参数作为数组而不是单独传递。 数组在JavaScript中更易于操作,从而为使用函数提供了更多的可能性。 这是使用applycall的示例:

var user = {
     greet: "Hello!",
     greetUser: function(userName) {
     console.log(this.greet + " " + userName);
     }
};

var greet1 = {
     greet: "Hola"
};

user.greetUser.call(greet1,"Rahul") // Output: "Hola Rahul"
user.greetUser.apply(greet1,["Rahul"]) // Output: "Hola Rahul"

bind方法允许您在不调用函数的情况下将参数传递给函数。 返回一个新函数,该函数具有在任何其他参数之前限定的参数。 这是一个例子:

var user = {
     greet: "Hello!",
     greetUser: function(userName) {
     console.log(this.greet + " " + userName);
}
};

var greetHola = user.greetUser.bind({greet: "Hola"});
var greetBonjour = user.greetUser.bind({greet: "Bonjour"});

greetHola("Rahul") // Output: "Hola Rahul"
greetBonjour("Rahul") // Output: "Bonjour Rahul"

JavaScript记忆

记忆化是一种优化技术,可通过存储昂贵操作的结果并在再次出现相同的一组输入时返回缓存的结果来加快函数执行速度。 JavaScript对象的行为类似于关联数组,因此很容易在JavaScript中实现备忘录。 例如,我们可以将递归阶乘函数转换为记忆阶乘函数,如下所示:

function memoizeFunction(func) {
  var cache = {};
  return function() {
          var key = arguments[0];
          if(cache[key]) {
          return cache[key];
          }
          else {
          var val = func.apply(this, arguments);
          cache[key] = val;
          return val;
          }
  };
}

var fibonacci = memoizeFunction(function(n) {
  return (n === 0 || n === 1) ? n : fibonacci(n - 1) + fibonacci(n - 2);
});

JavaScript方法重载

方法重载允许多个方法具有相同的名称但参数不同。 编译器或解释器根据传递的参数数量确定要调用的函数。 JavaScript不直接支持方法重载。 但是您可以实现非常类似的目标,如下所示:

function overloadMethod(object, name, fn){
     if(!object._overload){
    object._overload = {};
     }

     if(!object._overload[name]){
    object._overload[name] = {};
    }

     if(!object._overload[name][fn.length]){
object._overload[name][fn.length] = fn;
    }

     object[name] = function() {
         if(this._overload[name][arguments.length])
         return this._overload[name][arguments.length].apply(this, arguments);
     };


function Students(){
  overloadMethod(this, "find", function(){
          // Find a student by name
  });

overloadMethod(this, "find", function(first, last){
          // Find a student by first and last name
  });

}

var students = new Students();
students.find(); // Finds all
students.find("Rahul"); // Finds students by name
students.find("Rahul", "Mhatre"); // Finds users by first and last name

当您精通Node.js时,您会注意到有很多方法可以解决几乎所有问题。 但是采取正确的方法至关重要。 错误的方法将导致多种副作用,例如补丁程序或错误的应用程序或回归,迫使您重写整个逻辑。 另一方面,正确的方法将为健壮,高效和可扩展的应用程序奠定基础。

本文介绍的10个JavaScript概念是每个Node.js开发人员都应了解的基础知识。 但是它们只是冰山一角。 JavaScript功能强大且复杂。 使用的次数越多,您就会越了解真正JavaScript数量。 更好地理解这种广泛的语言肯定会帮助您避免错误。 同时,掌握正确的基础知识,您会看到不错的结果。

Rahul Mhatre是Software AG的开发团队负责人。 之前,他是Built.io(由Software AG收购)的技术架构师。

-

新技术论坛提供了一个以前所未有的深度和广度探索和讨论新兴企业技术的场所。 选择是主观的,是基于我们对InfoWorld读者认为最重要和最感兴趣的技术的选择。 InfoWorld不接受发布的营销担保,并保留编辑所有贡献内容的权利。 将所有查询发送到newtechforum@infoworld.com

From: https://www.infoworld.com/article/3196070/10-javascript-concepts-every-nodejs-developer-must-master.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值