목차
Node.js 이해
Variables
数值
布尔值
数组
对象字面量
函数
立即执行函数
匿名函数
高阶函数
코드 파일 variable.js
즉시 함수 실행
익명 함수
고차 함수
Node.js性能
大规模I/O问题
每一个请求创建一个进程
线程池
单线程模式
更多的Node.js细节
线程饥饿
数据密集型应用
V8 Javascript引擎
更多的Javascript
默认值
全等
null
透露模块模式
理解this
理解原型
错误处理
总结
웹 프론트엔드 JS 튜토리얼 Node.js가 무엇인지 이해하시나요?

Node.js가 무엇인지 이해하시나요?

Jun 26, 2017 am 11:47 AM
javascript node.js 공부하다 지도 시간

Node.js 이해

Node.js의 작동 방식을 이해하려면 먼저 Javascript를 서버 측 개발에 적합하게 만드는 몇 가지 주요 기능을 이해해야 합니다. Javascript는 단순하면서도 유연한 언어이며, 이러한 유연성을 통해 시간이 지나도 테스트를 견딜 수 있습니다. 함수 및 클로저와 같은 기능으로 인해 Javascript는 웹 개발에 이상적인 언어입니다.

자바스크립트는 신뢰할 수 없다는 편견이 있는데, 그렇지 않습니다. Javascript에 대한 사람들의 편견은 DOM에서 비롯됩니다. DOM은 Javascript가 브라우저와 상호 작용할 수 있도록 브라우저 제조업체에서 제공하는 API입니다. 브라우저 제조업체마다 구현하는 DOM에는 차이가 있습니다. 그러나 Javascript 자체는 다양한 브라우저와 Node.js에서 실행될 수 있는 잘 정의된 언어입니다. 이 섹션에서는 먼저 Javascript의 몇 가지 기본 사항과 Node.js가 Javascript를 사용하여 뛰어난 성능을 갖춘 웹 개발 플랫폼을 제공하는 방법을 소개합니다.

Variables

Javascript는 var 키워드를 사용하여 변수를 정의합니다. 예를 들어, 다음 코드는 foo라는 변수를 생성하고 이를 명령줄에 출력합니다. (nodevariable.js를 통해 명령줄에서 다음 코드 파일을 실행할 수 있습니다.)var关键字定义变量。例如下面的代码创建了一个名为foo的变量,并在命令行中输出。(可以通过node variable.js在命令行中执行下面的代码文件。)

代码文件 variable.js
var foo = 123;console.log(foo); // 123
로그인 후 복사

Javascript运行环境(浏览器或者Node.js)通常会定义一些我们可以使用的全局变量,例如console对象,console对象包含一个成员函数loglog函数能够接受任意数量的参数并输出它们。我们接下来会遇到更多的全局对象,你将会发现,Javascript具有一个优秀的编程语言应该包含的大部分特性。

数值

Javascript支持常见的算数操作符(+-*/%)。例如下列代码:

var foo = 3;
var bar = 5;
console.log(foo+1); //4
console.log(foo / bar); //0.6
console.log(foo * bar); //15
console.log(foo - bar); //-2
console.log(foo % 2); //取余:1
로그인 후 복사

布尔值

布尔值包括truefalse。你可以给变量赋值为truefalse,并对其进行布尔操作。例如下列代码:

var foo = true;
console.log(foo); //true//常见的布尔操作符号: &&,||, !
console.log(true && true); //true
console.log(true && false); /false
console.log(true || false); //true
console.log(false || false); //false
console.log(!true); //false
console.log(!false); //true
로그인 후 복사

数组

在Javascript中,我们可以通过[]创建数组。数组对象包含很多有用的函数,例如下列代码所示:

var foo = [];

foo.push(1); //添加到数组末尾
console.log(foo); // [1]

foo.unshift(2);  //添加到数组头部
console.log(foo); // [2, 1]//数组起始位置从0开始
console.log(foo[0]); // 2
로그인 후 복사

对象字面量

Javascript中通常使用对象字面量{}创建对象,例如下列代码所示:

var foo = {};
console.log(foo); // {}
foo.bar = 123;
console.log(foo); // {bar: 123}
로그인 후 복사

上面的代码在运行时添加对象属性,我们也可以在创建对象时定义对象属性:

var foo = {  bar: 123
};
console.log(foo); // {bar: 123}
로그인 후 복사

对象字面量中可以嵌套其它对象字面量,例如下列代码所示:

var foo = {
  bar: 123,
  bas: {
    bas1: 'some string',
    bas2: 345
  }
};
console.log(foo);
로그인 후 복사

当然,对象字面量中也可以包含数组:

var foo = {  bar: 123,  bas: [1,2,3]
};
console.log(foo);
로그인 후 복사

数组当中也可以包含对象字面量:

var foo = {  bar: 123,  bas: [{      qux: 1
    },
    {      qux: 2
    },
    {      qux: 3
    }]
};
console.log(foo.bar); //123
console.log(foo.bas[0].qux); // 1
console.log(foo.bas[2].qux); // 2
로그인 후 복사

函数

Javascript的函数非常强大,我们接下来将通过一系列的例子来逐渐了解它。
通常情况下的Javascript函数结构如下所示:

function functionName(){  //函数体
}
로그인 후 복사

Javascript的所有函数都有返回值。在没有显式声明返回语句的情况下,函数会返回undefined。例如下面代码所示:

function foo(){return 123;}console.log(foo); // 123function bar(){ }console.log(bar()); // undefined
로그인 후 복사

立即执行函数

我们在定义函数以后立即执行它,通过括号()包裹并调用函数。如下列代码所示:

(function foo(){
  console.log('foo was executed!');
})();
로그인 후 복사

出现立即执行函数的原因是为了创建新的变量作用域。ifelsewhile不会创建新的变量作用域,如下列代码所示:

var foo = 123;if(true){  var foo = 456;
}console.log(foo); // 456
로그인 후 복사

在Javascrit中,我们通过函数创建新的变量作用域,例如使用立即执行函数:

var foo = 123;if(true){
  (function(){      var foo = 456;
  })();
}console.log(foo); // 123
로그인 후 복사

在上面的代码中,我们没有给函数命名,这被称为匿名函数。

匿名函数

没有名字的函数被称为匿名函数。在Javascript中,我们可以把函数赋值给变量,如果准备将函数当作变量使用,就不需要给函数命名。下面给出了两种等价的写法:

var foo1 = function nameFunction(){  console.log('foo1');
}
foo1(); // foo1var foo2 = function(){  console.log('foo2');
}
foo2(); // foo2f
로그인 후 복사

据说如果一门编程语言能够把函数当作变量来对待,它就是一门优秀的编程语言,Javascript做到了这一点。

高阶函数

由于Javascript允许我们将函数赋值给变量,所以我们可以将函数作为参数传递给其它函数。将函数作为参数的函数被称为高阶函数。setTimeout就是常见的高阶函数。

setTimeout(function(){console.log('2000 milliseconds have passed since this demo started');
}, 2000);
로그인 후 복사

如果在Node.js中运行上面的代码,会看到命令窗口2秒钟后输出信息。在上面的代码中,我们传递了一个匿名函数作为setTimeout

코드 파일 variable.js
function foo(){  console.log('2000 milliseconds have passed since this demo started');
}
setTimeout(foo, 200);
로그인 후 복사

Javascript 런타임 환경(브라우저 또는 Node.js)은 일반적으로 console 개체와 같이 사용할 수 있는 일부 전역 변수를 정의합니다. console 개체에는 log< 멤버 함수가 포함되어 있습니다. /code >, <code>log 함수는 원하는 수의 매개변수를 허용하고 이를 출력할 수 있습니다. 다음에는 더 많은 전역 객체를 접하게 될 것이며, Javascript에는 좋은 프로그래밍 언어에 포함되어야 하는 대부분의 기능이 있다는 것을 알게 될 것입니다.

숫자 값

Javascript는 일반적인 산술 연산자(+, -, *, /, < code)를 지원합니다. >%). 예를 들어 다음 코드는

function outerFunction(arg){  var variableInOuterFunction = arg;  function bar(){console.log(variableInOuterFunction);
  }

  bar();
}

outerFunction(&#39;hello closure!&#39;);   // hello closure!
로그인 후 복사
로그인 후 복사

Boolean value

🎜Boolean 값에는 truefalse가 포함됩니다. 변수에 true 또는 false 값을 할당하고 해당 변수에 대해 부울 연산을 수행할 수 있습니다. 예를 들어 다음 코드는 🎜
function outerFunction(arg){  var variableInOuterFunction = arg;  return function(){console.log(variableInOuterFunction);
  }
}var innerFunction = outerFunction(&#39;hello closure!&#39;);

innerFunction(); // hello closure!
로그인 후 복사
로그인 후 복사
🎜Array🎜🎜Javascript에서는 []를 통해 배열을 생성할 수 있습니다. 배열 객체에는 다음 코드에 표시된 것처럼 유용한 함수가 많이 포함되어 있습니다. 🎜
function longRunningOperation(callback){
  setTimeout(callback, 3000);
}function UserClicked(){  console.log(&#39;starting a long operation&#39;);
  longRunningOperation(function(){      console.log(&#39;ending a long operation&#39;);
  })
}
UserClicked();
로그인 후 복사
로그인 후 복사
🎜객체 리터럴🎜🎜객체 리터럴 {}는 일반적으로 다음 코드에 표시된 것처럼 Javascript에서 객체를 생성하는 데 사용됩니다. 🎜
function longRunningOperation(callback){
  setTimeout(callback, 3000);
}function webRequest(request){  console.log(&#39;starting a long operation for request:&#39;, request.id);
  longRunningOperation(function(){console.log(&#39;ending a long operation for request:&#39;, request.id);
  });
}

webRequest({id: 1});
webRequest({id: 2});

//输出
//starting a long operation for request: 1//starting a long operation for request: 2//ending a long operation for request: 1//ending a long operation for request: 2
로그인 후 복사
로그인 후 복사
🎜 위의 코드는 런타임에 객체 속성을 추가합니다. 객체를 생성할 때 객체 속성을 정의할 수도 있습니다. 🎜
console.time(&#39;timer&#39;);
setTimeout(function(){  console.timeEnd(&#39;timer&#39;);  //timer: 1002.615ms
}, 1000)
로그인 후 복사
로그인 후 복사
🎜다음 코드에서 볼 수 있듯이 다른 객체 리터럴은 객체 리터럴에 중첩될 수 있습니다. 🎜
console.time(&#39;timeit&#39;);function fibonacci(n){  if(n<2){return 1;
  }else{return fibonacci(n-2) + fibonacci(n-1);
  }
}
fibonacci(44);console.timeEnd(&#39;timeit&#39;);  //我的电脑耗时 11863.331ms,每台电脑会有差异
로그인 후 복사
로그인 후 복사
🎜물론 객체 리터럴은 배열도 포함될 수 있습니다: 🎜
function fibonacci(n){  if(n<2){return 1;
  }else{return fibonacci(n-2) + fibonacci(n-1);
  }
}console.time(&#39;timer&#39;);
setTimeout(function(){  console.timeEnd(&#39;timer&#39;);  // 输出时间会大于 1000ms
}, 1000)

fibonacci(44);
로그인 후 복사
로그인 후 복사
🎜배열은 객체 리터럴도 포함할 수 있습니다. 🎜
var foo;console.log(foo);  //undefined
로그인 후 복사
로그인 후 복사
🎜Function🎜🎜Javascript 함수는 일련의 예제를 통해 점차적으로 이해하게 될 것입니다. 🎜일반적인 Javascript 함수 구조는 다음과 같습니다. 🎜
var foo = {bar: 123};
console.log(foo.bar); // 123
console.log(foo.bas); // undefined
로그인 후 복사
로그인 후 복사
🎜Javascript의 모든 함수에는 반환 값이 있습니다. 명시적인 반환 문이 없으면 함수는 정의되지 않음을 반환합니다. 예를 들어 다음 코드는 다음과 같습니다. 🎜
console.log(5 == &#39;5&#39;); // true
console.log(5 === &#39;5&#39;); // false
로그인 후 복사
로그인 후 복사

즉시 함수 실행

🎜함수를 정의한 후 즉시 실행하고 괄호 ()를 통해 함수를 래핑하고 호출합니다. 다음 코드와 같이 🎜
function printableMessage(){  var message = &#39;hello&#39;;  function setMessage(newMessage){if(!newMessage) throw new Error(&#39;cannot set empty message&#39;);
    message = newMessage;
  }  function getMessage(){return message;
  }  function printMessage(){
    console.log(message);
  }  return {
    setMessage: setMessage,
    getMessage: getMessage,
    printMessage: printMessage
  };
}var awesome1 = printableMessage();
awesome1.printMessage(); //hellovar awesome2 = printableMessage();
awesome2.setMessage(&#39;hi&#39;);
awesome2.printMessage(); // hi

awesome1.printMessage(); //hello
로그인 후 복사
로그인 후 복사
🎜즉시 실행 기능이 나타나는 이유는 새로운 변수 범위를 생성하기 위해서입니다. if, else, while은 다음 코드에 표시된 것처럼 새 변수 범위를 생성하지 않습니다. 🎜
var foo = {  bar: 123,  bas: function(){console.log(&#39;inside this.bar is: &#39;, this.bar);
  }
}console.log(&#39;foo.bar is:&#39;, foo.bar); //foo.bar is: 123
foo.bas(); //inside this.bar is: 123
로그인 후 복사
로그인 후 복사
🎜Javascript에서는 함수를 전달합니다. 예를 들어 즉시 실행 함수를 사용하여 새 변수 범위를 만듭니다. 🎜
function foo(){  console.log(&#39;is this called from globals? : &#39;, this === global); //true
}
foo();
로그인 후 복사
로그인 후 복사
🎜 위 코드에서는 함수에 이름을 지정하지 않았으며 이를 익명 함수라고 합니다. 🎜

익명 함수

🎜이름이 없는 함수를 익명 함수라고 합니다. Javascript에서는 함수를 변수에 할당할 수 있습니다. 함수를 변수로 사용하려는 경우 함수 이름을 지정할 필요가 없습니다. 두 가지 동등한 작성 방법이 아래에 나와 있습니다. 🎜
var foo = {  bar: 123
};function bas(){  if(this === global){console.log(&#39;called from global&#39;);
  }  if(this === foo){console.log(&#39;called from foo&#39;);
  }
}//指向global
bas(); //called from global//指向foo
foo.bas = bas;
foo.bas(); //called from foo
로그인 후 복사
로그인 후 복사
🎜프로그래밍 언어가 함수를 변수로 처리할 수 있다면 이는 훌륭한 프로그래밍 언어이며 Javascript가 이를 달성했다고 합니다. 🎜

고차 함수

🎜Javascript를 사용하면 함수를 변수에 할당할 수 있으므로 함수를 매개변수로 다른 함수에 전달할 수 있습니다. 함수를 인수로 취하는 함수를 고차 함수라고 합니다. setTimeout은 일반적인 고차 함수입니다. 🎜
function foo(){  this.foo = 123;
  console.log(&#39;Is this global? : &#39;, this == global);
}

foo(); // Is this global? : true
console.log(global.foo); //123var newFoo = new foo(); //Is this glocal ? : false
console.log(newFoo.foo); //123
로그인 후 복사
로그인 후 복사
🎜Node.js에서 위 코드를 실행하면 2초 후에 정보를 출력하는 명령창이 나옵니다. 위 코드에서는 setTimeout의 첫 번째 매개변수로 익명 함수를 전달했습니다. 일반 함수를 전달할 수도 있습니다: 🎜
var foo ={};
foo._proto_.bar = 123;
console.log(foo.bar); //123
로그인 후 복사
로그인 후 복사
🎜 이제 객체 리터럴과 함수에 대해 배웠으므로 클로저의 개념에 대해 알아 보겠습니다. 🎜🎜클로저🎜🎜클로저는 다른 함수 내부의 변수에 액세스할 수 있는 함수입니다. 함수 내부에 다른 함수를 정의하면 내부 함수가 외부 함수의 변수에 액세스할 수 있습니다. 이는 일반적인 클로저 형태입니다. 몇 가지 예를 들어 설명하겠습니다. 🎜아래 코드에서는 내부 함수가 외부 함수의 변수에 액세스할 수 있음을 확인할 수 있습니다. 🎜
function outerFunction(arg){  var variableInOuterFunction = arg;  function bar(){console.log(variableInOuterFunction);
  }

  bar();
}

outerFunction(&#39;hello closure!&#39;);   // hello closure!
로그인 후 복사
로그인 후 복사

令人惊喜的是:内部函数在外部函数返回之后依然可以访问外部函数作用域中的变量。这是因为,变量仍然被绑定于内部函数,不依赖于外部函数。例如:

function outerFunction(arg){  var variableInOuterFunction = arg;  return function(){console.log(variableInOuterFunction);
  }
}var innerFunction = outerFunction(&#39;hello closure!&#39;);

innerFunction(); // hello closure!
로그인 후 복사
로그인 후 복사

现在,我们已经了解了闭包,接下来,我们会探究一下使Javascript成为一门适合服务器端编程的语言的原因。

Node.js性能

Node.js致力于开发高性能应用程序。接下来的部分,我们会介绍大规模I/O问题,并分别展示传统方式及Node.js是如何解决这个问题的。

大规模I/O问题

大多数Web应用通过硬盘或者网络(例如查询另一台机器的数据库)获取数据,从硬盘或网络获取数据的速度远远慢于CPU的处理周期。当收到一个HTTP请求以后,我们需要从数据库获取数据,请求会一直等待直到获取数据完成。这些创建的连接和还未结束的请求会消耗服务器的资源(内存和CPU)。为了使同一台Web服务器能够处理大规模请求,我们需要解决大规模I/O问题。

每一个请求创建一个进程

传统的Web服务器为每一个请求创建一个新的进程,这是一种对内存和CPU开销都很昂贵的操作。PHP最开始就是采用的这种方法。在等待响应期间,进程仍然会消耗资源,并且进程的创建更慢。所以现代Web应用大多使用线程池的方法。

线程池

现代Web服务器使用线程池来处理每个请求。线程和进程相比,更加轻量级。在创建线程池以后,我们就不再需要为开始或结束进程而付出额外代价。当收到一个请求,我们为它分配一个线程。然而,线程池仍然会浪费一些资源。

单线程模式

我们知道为请求分别创建进程或者线程会导致系统资源浪费。与之相对,Node.js采取了单线程来处理请求。单线程服务器的性能优于线程池服务器的理念并不是Node.js首创,Nginx也是基于这种理念。Nginx是一种单线程服务器,能够处理极大数量的并发请求。
Javascript是单线程的,如果你有一个耗时操作(例如网络请求),就必须使用回调。下面的代码使用setTimeout模拟了一个耗时操作,可以用Node.js执行。

function longRunningOperation(callback){
  setTimeout(callback, 3000);
}function UserClicked(){  console.log(&#39;starting a long operation&#39;);
  longRunningOperation(function(){      console.log(&#39;ending a long operation&#39;);
  })
}
UserClicked();
로그인 후 복사
로그인 후 복사

让我们模拟一下Web请求:

function longRunningOperation(callback){
  setTimeout(callback, 3000);
}function webRequest(request){  console.log(&#39;starting a long operation for request:&#39;, request.id);
  longRunningOperation(function(){console.log(&#39;ending a long operation for request:&#39;, request.id);
  });
}

webRequest({id: 1});
webRequest({id: 2});

//输出
//starting a long operation for request: 1//starting a long operation for request: 2//ending a long operation for request: 1//ending a long operation for request: 2
로그인 후 복사
로그인 후 복사

更多的Node.js细节

Node.js的核心是一个event loopevent loop使得任何用户图形界面应用程序可以在任何操作系统中工作。当事件被触发时(例如:用户点击鼠标),操作系统调用程序的某个函数,程序执行函数中的代码。之后,程序准备响应已经在队列中的事件或尚未出现的事件。

线程饥饿

通常,在GUI程序中,当由一个事件调用的函数执行期间,其它事件不会被处理。因此,当你在相关函数中执行耗时操作时,GUI会变得无响应。这种CPU资源的短缺被成为饥饿
Node.js基于和GUI应用程序相同的event loop原则。因此,它也会面临饥饿的问题。为了帮助更好的理解,我们通过几个例子来说明:

console.time(&#39;timer&#39;);
setTimeout(function(){  console.timeEnd(&#39;timer&#39;);  //timer: 1002.615ms
}, 1000)
로그인 후 복사
로그인 후 복사

运行这段代码,与我们期望的相同,终端显示的数字在1000ms左右。
接下来我们想写一段耗时更长的代码,例如一个未经优化的计算Fibonacci数列的方法:

console.time(&#39;timeit&#39;);function fibonacci(n){  if(n<2){return 1;
  }else{return fibonacci(n-2) + fibonacci(n-1);
  }
}
fibonacci(44);console.timeEnd(&#39;timeit&#39;);  //我的电脑耗时 11863.331ms,每台电脑会有差异
로그인 후 복사
로그인 후 복사

现在我们可以模拟Node.js的线程饥饿。setTimeout用于在指定的时间以后调用函数,如果我们在函数调用以前,执行一个耗时方法,由于耗时方法占用CPU和Javascript线程,setTimeout指定的函数无法被及时调用,只能等待耗时方法运行结束以后被调用。例如下面的代码:

function fibonacci(n){  if(n<2){return 1;
  }else{return fibonacci(n-2) + fibonacci(n-1);
  }
}console.time(&#39;timer&#39;);
setTimeout(function(){  console.timeEnd(&#39;timer&#39;);  // 输出时间会大于 1000ms
}, 1000)

fibonacci(44);
로그인 후 복사
로그인 후 복사

所以,如果你面临CPU密集型场景,Node.js并不是最佳选择,但也很难找到其它合适的平台。但是Node.js非常适用于I/O密集型场景。

数据密集型应用

Node.js适用于I/O密集型。单线程机制意味着Node.js作为Web服务器会占用更少的内存,能够支持更多的请求。与执行代码相比,从数据库获取数据需要花费更多的时间。下图展示了传统的线程池模型的服务器是如何处理用户请求的:


Node.js服务器处理请求的方式如下图。因为所有的工作都在单线程内完成,所以消耗更少的内存,同时因为不需要切换线程,所以CPU负载更小。

V8 Javascript引擎

Node.js中的所有Javascript通过V8 Javascript引擎执行。V8产生于谷歌Chrome项目,V8在Chrome中用于运行Javascript。V8不仅速度更快,而且很容易被集成到其它项目。

更多的Javascript

精通Javascript使得Node.js开发者不仅能够写出更加容易维护的项目,而且能够利用到Javascript生态链的优势。

默认值

Javascript变量的默认值是undefined。如下列代码所示:

var foo;console.log(foo);  //undefined
로그인 후 복사
로그인 후 복사

变量不存在的属性也会返回undefined

var foo = {bar: 123};
console.log(foo.bar); // 123
console.log(foo.bas); // undefined
로그인 후 복사
로그인 후 복사

全等

需要注意Javascript当中 =====的区别。==会对变量进行类型转换,===不会。推荐的用法是总是使用===

console.log(5 == &#39;5&#39;); // true
console.log(5 === &#39;5&#39;); // false
로그인 후 복사
로그인 후 복사

null

null是一个特殊的Javascript对象,用于表示空对象。而undefined用于表示变量不存在或未初始化。我们不需要给变量赋值为undefined,因为undefined是变量的默认值。

透露模块模式

透露模块模式的关键在于Javascript对闭包的支持以及能够返回任意对象的能力。如下列代码所示:

function printableMessage(){  var message = &#39;hello&#39;;  function setMessage(newMessage){if(!newMessage) throw new Error(&#39;cannot set empty message&#39;);
    message = newMessage;
  }  function getMessage(){return message;
  }  function printMessage(){
    console.log(message);
  }  return {
    setMessage: setMessage,
    getMessage: getMessage,
    printMessage: printMessage
  };
}var awesome1 = printableMessage();
awesome1.printMessage(); //hellovar awesome2 = printableMessage();
awesome2.setMessage(&#39;hi&#39;);
awesome2.printMessage(); // hi

awesome1.printMessage(); //hello
로그인 후 복사
로그인 후 복사

理解this

this总是指向调用函数的对象。例如:

var foo = {  bar: 123,  bas: function(){console.log(&#39;inside this.bar is: &#39;, this.bar);
  }
}console.log(&#39;foo.bar is:&#39;, foo.bar); //foo.bar is: 123
foo.bas(); //inside this.bar is: 123
로그인 후 복사
로그인 후 복사

由于函数basfoo对象调用,所以this指向foo。如果是纯粹的函数调用,则this指向全局变量。例如:

function foo(){  console.log(&#39;is this called from globals? : &#39;, this === global); //true
}
foo();
로그인 후 복사
로그인 후 복사

如果我们在浏览器中执行上面的代码,全局变量global会变为window
如果函数的调用对象改变,this的指向也会改变:

var foo = {  bar: 123
};function bas(){  if(this === global){console.log(&#39;called from global&#39;);
  }  if(this === foo){console.log(&#39;called from foo&#39;);
  }
}//指向global
bas(); //called from global//指向foo
foo.bas = bas;
foo.bas(); //called from foo
로그인 후 복사
로그인 후 복사

如果通过new操作符调用函数,函数内的this会指向由new创建的对象。

function foo(){  this.foo = 123;
  console.log(&#39;Is this global? : &#39;, this == global);
}

foo(); // Is this global? : true
console.log(global.foo); //123var newFoo = new foo(); //Is this glocal ? : false
console.log(newFoo.foo); //123
로그인 후 복사
로그인 후 복사

通过上面代码,我们可以看到,在通过new调用函数时,函数内的this指向发生改变。

理解原型

Javascript通过new操作符及原型属性可以模仿面向对象的语言。每个Javascript对象都有一个被称为原型的内部链接指向其他对象。
当我们调用一个对象的属性,例如:foo.bar,Javascript会检查foo对象是否存在bar属性,如果不存在,Javascript会检查bar属性是否存在于foo._proto_,以此类推,直到对象不存在_proto_。如果在任何层级发现属性的值,则立即返回,否则,返回undefined

var foo ={};
foo._proto_.bar = 123;
console.log(foo.bar); //123
로그인 후 복사
로그인 후 복사

当我们通过new操作符创建对象时,对象的_proto_会被赋值为函数的prototype属性,例如:

function foo(){};
foo.prototype.bar = 123;var bas = new foo();console.log(bas._proto_ === foo.prototype); //trueconsole.log(bas.bar);
로그인 후 복사

函数的所有实例共享相同的prototype

function foo(){};
foo.prototype.bar = 123;

var bas = new foo();
var qux = new foo();
console.log(bas.bar); //123
console.log(qux.bar); //123

foo.prototype.bar = 456;
console.log(bas.bar); //456
console.log(qux.bar); //456
로그인 후 복사

只有当属性不存在时,才会访问原型,如果属性存在,则不会访问原型。

function foo(){};
foo.prototype.bar = 123;var bas = new foo();var qux = new foo();

bas.bar = 456;console.log(bas.bar);//456console.log(qux.bar); //123
로그인 후 복사

上面的代码表明,如果修改了bas.bar, bas._proto_.bar就不再被访问。

错误处理

Javascript的异常处理机制类似其它语言,通过throw关键字抛出异常,通过catch关键字捕获异常。例如:

try{
  console.log(&#39;About to throw an error&#39;);  throw new Error(&#39;Error thrown&#39;);
}
catch(e){
  console.log(&#39;I will only execute if an error is thrown&#39;);
  console.log(&#39;Error caught: &#39;, e.message);
}finally{
  console.log(&#39;I will execute irrespective of an error thrown&#39;);
}
로그인 후 복사

总结

本章,我们介绍了一些Node.js及Javascript的重要概念,知道了Node.js适用于开发数据密集型应用程序。下章我们将开始介绍如何使用Node.js开发应用程序。


위 내용은 Node.js가 무엇인지 이해하시나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. 크로스 플레이가 있습니까?
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Dewu 사용법 튜토리얼 Dewu 사용법 튜토리얼 Mar 21, 2024 pm 01:40 PM

Dewu APP는 현재 매우 인기 있는 브랜드 쇼핑 소프트웨어이지만 대부분의 사용자는 Dewu APP의 기능을 사용하는 방법을 모릅니다. 다음으로 편집기는 Dewuduo를 사용자에게 제공합니다. 관심 있는 사용자는 와서 살펴볼 수 있습니다! Dewu 이용방법 튜토리얼 [2024-03-20] Dewu 할부구매 이용방법 [2024-03-20] Dewu 쿠폰 받는 방법 [2024-03-20] Dewu 매뉴얼 고객센터 찾는 방법 [2024-03- 20] 듀우 픽업 코드 확인 방법 [2024-03-20] 듀우 구매처 찾기 [2024-03-20] 듀우 VIP 개설 방법 [2024-03-20] 듀우 반품, 교환 신청 방법

여름에는 꼭 무지개를 찍어보세요 여름에는 꼭 무지개를 찍어보세요 Jul 21, 2024 pm 05:16 PM

여름에 비가 내린 후에는 아름답고 마법 같은 특별한 날씨 장면인 무지개를 자주 볼 수 있습니다. 이 역시 사진에서 볼 수 있는 보기 드문 장면으로, 매우 포토제닉하다. 무지개가 나타나는 데에는 몇 가지 조건이 있습니다. 첫째, 공기 중에 충분한 물방울이 있고, 둘째, 태양이 낮은 각도로 빛납니다. 따라서 비가 그친 후 오후에 무지개를 보는 것이 가장 쉽습니다. 그러나 무지개의 형성은 날씨, 빛, 기타 조건의 영향을 크게 받기 때문에 일반적으로 짧은 시간 동안만 지속되며, 가장 잘 볼 수 있고 촬영할 수 있는 시간은 더욱 짧습니다. 그러면 무지개를 만났을 때 어떻게 제대로 기록하고 고품질로 사진을 찍을 수 있습니까? 1. 무지개를 찾아보세요. 위에서 언급한 조건 외에도 무지개는 대개 햇빛 방향으로 나타납니다. 즉, 태양이 서쪽에서 동쪽으로 빛날 경우 무지개가 동쪽에서 나타날 확률이 높습니다.

WeChat에서 결제 소리를 끄는 방법에 대한 튜토리얼 WeChat에서 결제 소리를 끄는 방법에 대한 튜토리얼 Mar 26, 2024 am 08:30 AM

1. 먼저 위챗을 엽니다. 2. 오른쪽 상단의 [+]를 클릭하세요. 3. QR코드를 클릭하시면 결제가 진행됩니다. 4. 오른쪽 상단에 있는 세 개의 작은 점을 클릭하세요. 5. 결제도착 음성알림을 클릭하시면 종료됩니다.

photoshopcs5는 어떤 소프트웨어인가요? -photoshopcs5 사용법 튜토리얼 photoshopcs5는 어떤 소프트웨어인가요? -photoshopcs5 사용법 튜토리얼 Mar 19, 2024 am 09:04 AM

PhotoshopCS는 Photoshop Creative Suite의 약자로 Adobe에서 제작한 소프트웨어입니다. 그래픽 디자인 및 이미지 처리에 널리 사용됩니다. PS를 처음 배우는 사용자로서 오늘은 photoshopcs5가 무엇인지, photoshopcs5를 사용하는 방법에 대해 설명하겠습니다. . 1. Photoshop CS5는 어떤 소프트웨어입니까? Adobe Photoshop CS5 Extended는 영화, 비디오 및 멀티미디어 분야의 전문가, 3D 및 애니메이션을 사용하는 그래픽 및 웹 디자이너, 엔지니어링 및 과학 분야의 전문가에게 이상적입니다. 3D 이미지를 렌더링하고 이를 2D 합성 이미지로 병합합니다. 쉽게 비디오 편집

전문가가 가르쳐드립니다! Huawei 휴대폰에서 긴 사진을 자르는 올바른 방법 전문가가 가르쳐드립니다! Huawei 휴대폰에서 긴 사진을 자르는 올바른 방법 Mar 22, 2024 pm 12:21 PM

스마트폰의 지속적인 발전과 함께 휴대폰의 기능은 점점 더 강력해졌고, 그 중 장사진 촬영 기능은 많은 사용자들이 일상생활에서 사용하는 중요한 기능 중 하나로 자리 잡았다. 긴 스크린샷은 사용자가 쉽게 보고 공유할 수 있도록 긴 웹페이지, 대화 기록, 사진을 한 번에 저장하는 데 도움이 됩니다. 많은 휴대폰 브랜드 중에서 Huawei 휴대폰은 사용자들로부터 높은 평가를 받는 브랜드 중 하나이며, 긴 사진을 자르는 기능도 높은 평가를 받고 있습니다. 이 기사에서는 Huawei 휴대폰으로 장사진을 찍는 올바른 방법과 Huawei 휴대폰을 더 잘 활용하는 데 도움이 되는 몇 가지 전문가 팁을 소개합니다.

워드에서 근수를 입력하는 방법을 함께 알아볼까요? 워드에서 근수를 입력하는 방법을 함께 알아볼까요? Mar 19, 2024 pm 08:52 PM

Word에서 텍스트 내용을 편집할 때 수식 기호를 입력해야 하는 경우가 있습니다. 어떤 사람들은 Word에서 근수를 입력하는 방법을 모르기 때문에 편집자에게 Word에서 근수를 입력하는 방법에 대한 튜토리얼을 친구들과 공유해달라고 요청했습니다. 그것이 내 친구들에게 도움이 되기를 바랍니다. 먼저 컴퓨터에서 Word 소프트웨어를 연 다음 편집하려는 파일을 열고 루트 기호를 삽입해야 하는 위치로 커서를 이동합니다. 아래 그림 예를 참조하세요. 2. [삽입]을 선택한 후, 기호에서 [수식]을 선택하세요. 아래 그림의 빨간색 원과 같이 3. 아래의 [새 수식 삽입]을 선택하세요. 아래 그림의 빨간색 원과 같이 4. [부수]를 선택한 후 해당 부수를 선택합니다. 아래 그림의 빨간색 원에 표시된 대로:

PHP 튜토리얼: int 유형을 문자열로 변환하는 방법 PHP 튜토리얼: int 유형을 문자열로 변환하는 방법 Mar 27, 2024 pm 06:03 PM

PHP 튜토리얼: Int 유형을 문자열로 변환하는 방법 PHP에서는 정수 데이터를 문자열로 변환하는 것이 일반적인 작업입니다. 이 튜토리얼에서는 특정 코드 예제를 제공하면서 PHP의 내장 함수를 사용하여 int 유형을 문자열로 변환하는 방법을 소개합니다. 캐스트 사용: PHP에서는 캐스트를 사용하여 정수 데이터를 문자열로 변환할 수 있습니다. 이 방법은 매우 간단합니다. 정수 데이터 앞에 (문자열)을 추가하면 문자열로 변환됩니다. 아래는 간단한 샘플 코드입니다.

Honor 휴대폰 Hongmeng 시스템 업그레이드 튜토리얼 Honor 휴대폰 Hongmeng 시스템 업그레이드 튜토리얼 Mar 23, 2024 pm 12:45 PM

Honor 휴대폰은 뛰어난 성능과 안정적인 시스템으로 인해 항상 소비자들의 선호를 받아왔습니다. 최근 Honor 휴대폰은 새로운 Hongmeng 시스템을 출시하여 많은 사용자의 관심과 기대를 불러일으켰습니다. 홍멍(Hongmeng) 시스템은 '세계를 통합하는' 시스템으로 알려져 있으며, 더욱 원활한 작동 경험과 높은 보안성을 갖추고 있어 사용자가 스마트폰의 새로운 세계를 경험할 수 있습니다. 많은 사용자들이 Honor 휴대폰 시스템을 Hongmeng 시스템으로 업그레이드하고 싶다고 표현했습니다. 이제 Honor 휴대폰의 Hongmeng 시스템 업그레이드 튜토리얼을 살펴보겠습니다. 첫째로, 나는

See all articles