这只是个人学习的笔记
1.更新npm包:
npm install npm -g
安装node模块语法:
npm install moduleName
安装好的模块包都会放在node_modules文件夹下
例子:
npm install express;
使用:
var express = require(‘express’);
全局安装与本地安装:
npm install express #本地安装
npm install express -g #全局安装
如果出现以下错误:
npm err! Error: connect ECONNREFUSED 127.0.0.1:8087
解决办法为:
npm config set proxy null;
本地安装
● 1. 将安装包放在 ./node_modules 下(运行 npm 命令时所在的目录),如果没有 node_modules 目录,会在当前执行 npm 命令的目录下生成 node_modules 目录。
● 2. 可以通过 require() 来引入本地安装的包。
全局安装
● 1. 将安装包放在 /usr/local 下或者你 node 的安装目录。
● 2. 可以直接在命令行里使用。
npm link
npm list -g 查看全局安装的包
npm list 模块名 查看模块的版本好
使用 package.json
Package.json 属性说明
● name - 包名。
● version - 包的版本号。
● description - 包的描述。
● homepage - 包的官网 url 。
● author - 包的作者姓名。
● contributors - 包的其他贡献者姓名。
● dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。
● repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。
● main - main 字段是一个模块ID,它是一个指向你程序的主要项目。就是说,如果你包的名字叫 express,然后用户安装它,然后require("express")。
● keywords - 关键字
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install [name]
卸载模块
npm uninstall express
npm ls 查看模块是否存在
更新模块
npm update express
搜索模块
npm search express
创建模块
npm init
$ npm adduser
Username: mcmohd
Password:
Email: (this IS public) mcmohd@gmail.com
npm publish
在package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试。
使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人
使用npm unpublish @可以撤销发布自己发布过的某个版本代码
使用淘宝 NPM 镜像
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install [name] http://npm.taobao.org/。
Node.js REPL(交互式解释器)
循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。
变量声明需要使用 var 关键字,如果没有使用 var 关键字变量会直接打印出来
声明变量:
var x=3 ;
console.log(x);
do{
}while(x>5);
下划线(_)变量
你可以使用下划线(_)获取表达式的运算结果
REPL 命令
● ctrl + c - 退出当前终端。
● ctrl + c 按下两次 - 退出 Node REPL。
● ctrl + d - 退出 Node REPL.
● 向上/向下 键 - 查看输入的历史命令
● tab 键 - 列出当前命令
● .help - 列出使用命令
● .break - 退出多行表达式
● .clear - 退出多行表达式
● .save filename - 保存当前的 Node REPL 会话到指定文件
● .load filename - 载入当前 Node REPL 会话的文件内容。
Node.js 异步编程的直接体现就是回调
Node.js 事件循环
事件驱动程序
在 Node 应用程序中,执行异步操作的函数将回调函数作为最后一个参数, 回调函数接收错误对象作为第一个参数。
Node.js EventEmitter
Node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.readStream对象会在文件被打开的时候发出一个事件。 所有这些产生事件的对象都是 events.EventEmitter 的实例
EventEmitter 类
方法 序号方法 & 描述
1 addListener(event, listener)
为指定事件添加一个监听器到监听器数组的尾部。
2 on(event, listener)
为指定事件注册一个监听器,接受一个字符串 event
和一个回调函数。server.on(‘connection’, function (stream) {
console.log(‘someone connected!’); });
3 once(event, listener)
为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。server.once(‘connection’,
function (stream) { console.log(‘Ah, we have our first user!’);
4 removeListener(event, listener)
移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器。
它接受两个参数,第一个是事件名称,第二个是回调函数名称。 var callback > = function(stream) {
console.log(‘someone connected!’); }; server.on(‘connection’,
callback); // … server.removeListener(‘connection’,
callback);
5 removeAllListeners([event])
移除所有事件的所有监听器,
6 setMaxListeners(n)
默认情况下, EventEmitters
如果你添加的监听器超过 10 个就会输出警告信息。 setMaxListeners
7 listeners(event)
返回指定事件的监听器数组。
8 emit(event, [arg1][arg2], […])
按参数的顺序执行每个监听器,如果事件有注册监听返回 true,否则返回 false。
var events = require("events");
var evnetEmitter = new events.EventEmitter();
var listener1 = function listener1(){
console.log('listener1-=====');
}
var listener2 = function listener2(){
console.log('listener2-=====');
}
evnetEmitter.addListener("connection", listener1);
evnetEmitter.on('connection',listener2);
var eventListeners =
require('events').EventEmitter.listenerCount(evnetEmitter,'connection');
console.log(eventListeners+'个监听器监听连接事件.');
evnetEmitter.emit('connection');
evnetEmitter.removeListener("connection", listener1);
console.log("listener1 不再监听");
evnetEmitter.emit('connection');
eventListeners = require('events').EventEmitter.listenerCount(evnetEmitter,"connection");
console.log(eventListeners + " 个监听器监听连接事件。");
console.log("程序执行完毕");
继承 EventEmitter
Node.js Buffer(缓冲区)
创建 Buffer 类
方法 1
var buf = new Buffer(10);
方法 2
var buf = new Buffer([10, 20, 30, 40, 50]);
方法 3
var buf = new Buffer("www.runoob.com", "utf-8");
写入缓冲区
语法
写入 Node 缓冲区的语法如下所示:
buf.write(string[, offset[, length]][, encoding])
参数
参数描述如下:
● string - 写入缓冲区的字符串。
● offset - 缓冲区开始写入的索引值,默认为 0 。
● length - 写入的字节数,默认为 buffer.length
● encoding - 使用的编码。默认为 'utf8' 。
返回值
返回实际写入的大小。如果 buffer 空间不足, 则只会写入部分字符串
从缓冲区读取数据
buf.toString([encoding[, start[, end]]])
语法
读取 Node 缓冲区数据的语法如下所示:
buf.toString([encoding[, start[, end]]])
参数
参数描述如下:
● encoding - 使用的编码。默认为 'utf8' 。
● start - 指定开始读取的索引位置,默认为 0。
● end - 结束位置,默认为缓冲区的末尾。
返回值
解码缓冲区数据并使用指定的编码返回字符串。
buf.toJSON(buf);
缓冲区合并
Buffer.concat(list[, totalLength])
缓冲区比较
buf.compare(otherBuffer);
拷贝缓冲区
var buffer1 = new Buffer('ABC');
// 拷贝一个缓冲区
var buffer2 = new Buffer(3);
buffer1.copy(buffer2);
console.log("buffer2 content: " + buffer2.toString());
缓冲区裁剪
var buffer1 = new Buffer('runoob');
// 剪切缓冲区
var buffer2 = buffer1.slice(0,2);
console.log("buffer2 content: " + buffer2.toString());
缓冲区长度
buf.length
Node.js Stream(流)
Readable - 可读操作。
Writable - 可写操作。
Duplex - 可读可写操作.
Transform - 操作被写入数据,然后读出结果。
所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:
data - 当有数据可读时触发。 end - 没有更多的数据可读时触发。
error - 在接收和写入过程中发生错误时触发。
finish - 所有数据已被写入到底层系统时触发读取数据 var fs = require(“fs”); var data = ”;
创建可读流
var readerStream = fs.createReadStream(‘input.txt’);
设置编码为 utf8。
readerStream.setEncoding(‘UTF8’);
处理流事件 –> data, end, and error
readerStream.on(‘data’, function(chunk) { data += chunk; });
readerStream.on(‘end’,function(){ console.log(data); });
readerStream.on(‘error’, function(err){ console.log(err.stack); });
console.log(“程序执行完毕”);
var fs = require(“fs”); var data = ‘www.baidu.com’;
var writeStream = fs.createWriteStream(‘input.txt’);
writeStream.write(data,’UTF8’);
writeStream.end();
writeStream.on(‘finish’,function(){ console.log(‘write end….
finish’); });writeStream.on(‘error’,function(){ console.log(err.stack); });
console.log(“程序执行结束”);
var fs = require(“fs”);
var readerSream = fs.createReadStream(‘input.txt’);
var writeStream = fs.createWriteStream(‘output.txt’);
readerSream.pipe(writeStream);
console.log(“ok”);
链式流
var fs = require("fs");
var zilb = require("zlib");
fs.createReadStream("input.txt").pipe(zilb.createGzip()).pipe(fs.createWriteStream('input.txt.gz'));
console.log("文件压缩完成")
var fs = require("fs");
var zlib = require("zlib");
fs.createReadStream('input.txt.gz').pipe(zlib.createGunzip()).pipe(fs.createWriteStream('test.txt'));
console.log("end")
Node.js模块系统
以上实例中,代码 require(‘./hello’) 引入了当前目录下的hello.js文件(./ 为当前目录,node.js默认后缀为js)。
Node.js 提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象
//hello.js
function Hello() { var name; this.setName = function(thyName) {
name = thyName; }; this.sayHello = function() {
console.log(‘Hello ’ + name); }; }; module.exports = Hello;
require方法接受以下几种参数的传递:
● http、fs、path等,原生模块。
● ./mod或../mod,相对路径的文件模块。
● /pathtomodule/mod,绝对路径的文件模块。
● mod,非原生模块的文件模块
function say(word) { console.log(word); }
function execute(someFunction, value) { someFunction(value); }
execute(say, “Hello”);
匿名函数
function execute(someFunction, value) { someFunction(value); }
execute(function(word){ console.log(word) }, “Hello”);
函数传递是如何让HTTP服务器工作的
var http = require(“http”);
function onRequest(request, response) { response.writeHead(200,
{“Content-Type”: “text/plain”}); response.write(“Hello World”);
response.end(); }http.createServer(onRequest).listen(8888);
Node.js 路由
function route(pathname) { console.log(“About to route a request for
” + pathname); }exports.route = route;
var http = require(“http”); var url = require(“url”);
function start(route) { function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log(“Request for ” + pathname + ” received.”);route(pathname); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello World"); response.end(); }
http.createServer(onRequest).listen(8888); console.log(“Server has
started.”); }exports.start = start;
var server = require(“./server”); var router = require(“./router”);
server.start(router.route);
Node.js 全局对象
global 最根本的作用是作为全局变量的宿主。按照 ECMAScript 的定义,满足以下条 件的变量是全局变量:
● 在最外层定义的变量;
● 全局对象的属性;
● 隐式定义的变量(未定义直接赋值的变量)。
注意: 永远使用 var 定义变量以避免引入全局变量,因为全局变量会污染 命名空间,提高代码的耦合风险。
__filename
__filename 表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径。
__dirname
__dirname 表示当前执行脚本所在的目录。
setTimeout(cb, ms)
setTimeout(cb, ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。:setTimeout() 只执行一次指定函数。
返回一个代表定时器的句柄值。
clearTimeout(t)
clearTimeout( t ) 全局函数用于停止一个之前通过 setTimeout() 创建的定时器。 参数 t 是通过
setTimeout() 函数创建的定时器。
setInterval(cb, ms)
setInterval(cb, ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。 返回一个代表定时器的句柄值。可以使用
clearInterval(t) 函数来清除定时器。 setInterval() 方法会不停地调用函数,直到 clearInterval()
被调用或窗口被关闭。
console
console.trace();
process
1 bort()
这将导致 node 触发 abort 事件。会让 node 退出并生成一个核心文件。
2 chdir(directory)
改变当前工作进程的目录,如果操作失败抛出异常。
3 cwd()
返回当前进程的工作目录
4 exit([code])
使用指定的 code 结束进程。如果忽略,将会使用 code 0。
5 getgid()
获取进程的群组标识(参见 getgid(2))。获取到得时群组的数字 id,而不是名字。
注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
6 setgid(id)
设置进程的群组标识(参见 setgid(2))。可以接收数字 ID 或者群组名。如果指定了群组名,会阻塞等待解析为数字 ID 。
注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
7 getuid()
获取进程的用户标识(参见 getuid(2))。这是数字的用户 id,不是用户名。
注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
8 setuid(id)
设置进程的用户标识(参见setuid(2))。接收数字 ID或字符串名字。果指定了群组名,会阻塞等待解析为数字 ID 。
注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
9 getgroups()
返回进程的群组 iD 数组。POSIX 系统没有保证一定有,但是 node.js 保证有。
注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
10 setgroups(groups)
设置进程的群组 ID。这是授权操作,所有你需要有 root 权限,或者有 CAP_SETGID 能力。
注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
11 initgroups(user, extra_group)
读取 /etc/group ,并初始化群组访问列表,使用成员所在的所有群组。这是授权操作,所有你需要有 root 权限,或者有 CAP_SETGID 能力。
注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
12 kill(pid[, signal])
发送信号给进程. pid 是进程id,并且 signal 是发送的信号的字符串描述。信号名是字符串,比如 ‘SIGINT’ 或 ‘SIGHUP’。如果忽略,信号会是 ‘SIGTERM’。
13 memoryUsage()
返回一个对象,描述了 Node 进程所用的内存状况,单位为字节。
14 nextTick(callback)
一旦当前事件循环结束,调用回到函数。
15 umask([mask])
设置或读取进程文件的掩码。子进程从父进程继承掩码。如果mask 参数有效,返回旧的掩码。否则,返回当前掩码。
16 uptime()
返回 Node 已经运行的秒数。
17 hrtime()
返回当前进程的高分辨时间,形式为 [seconds, nanoseconds]数组。它是相对于过去的任意事件。该值与日期无关,因此不受时钟漂移的影响。主要用途是可以通过精确的时间间隔,来衡量程序的性能。
你可以将之前的结果传递给当前的 process.hrtime() ,会返回两者间的时间差,用来基准和测量时间间隔
Node.js 常用工具
util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数
util.inspect
Sub 仅仅继承了Base 在原型中定义的函数,而构造函数内部创造的 base 属 性和 sayHello 函数都没有被 Sub 继承。
同时,在原型中定义的属性不会被console.log 作 为对象的属性输出。如果我们去掉 objSub.sayHello(); 这行的注释,将会看到:
util.inspect
util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换 为字符串的方法,通常用于调试和错误输出。它至少接受一个参数 object,即要转换的对象。
util.isArray(object)
如果给定的参数 "object" 是一个数组返回true,否则返回false。
util.isRegExp(object)
util.isDate(object)
util.isError(object)
Node.js 文件系统
Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()
fs.open(path, flags[, mode], callback)
fs.stat(path, callback)
fs.read(fd, buffer, offset, length, position, callback)
fs.close(fd, callback)
截取文件
fs.ftruncate(fd, len, callback)
删除文件
fs.unlink(path, callback)
创建目录
fs.mkdir(path[, mode], callback)
读取目录
fs.readdir(path, callback)
删除目录
fs.rmdir(path,callback)
获取GET请求内容
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
res.end(util.inspect(url.parse(req.url, true)));
}).listen(3000);
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
// 解析 url 参数
var params = url.parse(req.url, true).query;
res.write("网站名:" + params.name);
res.write("\n");
res.write("网站 URL:" + params.url);
res.end();
}).listen(3000);
var http = require('http');
var querystring = require('querystring');
http.createServer(function(req, res){
// 定义了一个post变量,用于暂存请求体的信息
var post = '';
// 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
req.on('data', function(chunk){
post += chunk;
});
// 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
req.on('end', function(){
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
Node.js Net 模块
1 net.createServer([options][, connectionListener])
创建一个 TCP 服务器。参数 connectionListener 自动给 ‘connection’ 事件创建监听器。
2 net.connect(options[, connectionListener])
返回一个新的 ‘net.Socket’,并连接到指定的地址和端口。
当 socket 建立的时候,将会触发 ‘connect’ 事件。
3 net.createConnection(options[, connectionListener])
创建一个到端口 port 和 主机 host的 TCP 连接。 host 默认为 ‘localhost’。
4 net.connect(port[, host][, connectListener])
创建一个端口为 port 和主机为 host的 TCP 连接 。host 默认为 ‘localhost’。参数 connectListener 将会作为监听器添加到 ‘connect’ 事件。返回 ‘net.Socket’。
5 net.createConnection(port[, host][, connectListener])
创建一个端口为 port 和主机为 host的 TCP 连接 。host 默认为 ‘localhost’。参数 connectListener 将会作为监听器添加到 ‘connect’ 事件。返回 ‘net.Socket’。
6 net.connect(path[, connectListener])
创建连接到 path 的 unix socket 。参数 connectListener 将会作为监听器添加到 ‘connect’ 事件上。返回 ‘net.Socket’。
7 net.createConnection(path[, connectListener])
创建连接到 path 的 unix socket 。参数 connectListener 将会作为监听器添加到 ‘connect’ 事件。返回 ‘net.Socket’。
8 net.isIP(input)
检测输入的是否为 IP 地址。 IPV4 返回 4, IPV6 返回 6,其他情况返回 0。
9 net.isIPv4(input)
如果输入的地址为 IPV4, 返回 true,否则返回 false。
10 net.isIPv6(input)
如果输入的地址为 IPV6, 返回 true,否则返回 false。
net.Server
1 server.listen(port[, host][, backlog][, callback])
监听指定端口 port 和 主机 host ac连接。 默认情况下 host 接受任何 IPv4 地址(INADDR_ANY)的直接连接。端口 port 为 0 时,则会分配一个随机端口。
2 server.listen(path[, callback])
通过指定 path 的连接,启动一个本地 socket 服务器。
3 server.listen(handle[, callback])
通过指定句柄连接。
4 server.listen(options[, callback])
options 的属性:端口 port, 主机 host, 和 backlog, 以及可选参数 callback 函数, 他们在一起调用server.listen(port, [host], [backlog], [callback])。还有,参数 path 可以用来指定 UNIX socket。
5 server.close([callback])
服务器停止接收新的连接,保持现有连接。这是异步函数,当所有连接结束的时候服务器会关闭,并会触发 ‘close’ 事件。
6 server.address()
操作系统返回绑定的地址,协议族名和服务器端口。
7 server.unref()
如果这是事件系统中唯一一个活动的服务器,调用 unref 将允许程序退出。
8 server.ref()
与 unref 相反,如果这是唯一的服务器,在之前被 unref 了的服务器上调用 ref 将不会让程序退出(默认行为)。如果服务器已经被 ref,则再次调用 ref 并不会产生影响。
9 server.getConnections(callback)
异步获取服务器当前活跃连接的数量。当 socket 发送给子进程后才有效;回调函数有 2 个参数 err 和 count。
事件
1 listening
当服务器调用 server.listen 绑定后会触发。
2 connection
当新连接创建后会被触发。socket 是 net.Socket实例。
3 close
服务器关闭时会触发。注意,如果存在连接,这个事件不会被触发直到所有的连接关闭。
4 error
发生错误时触发。’close’ 事件将被下列事件直接调用。
net.Socket
net.Socket 对象是 TCP 或 UNIX Socket 的抽象。net.Socket 实例实现了一个双工流接口。 他们可以在用户创建客户端(使用 connect())时使用, 或者由 Node 创建它们,并通过 connection 服务器事件传递给用户。
1 lookup
在解析域名后,但在连接前,触发这个事件。对 UNIX sokcet 不适用。
2.connect
成功建立 socket 连接时触发。
3 data
当接收到数据时触发。
4 end
当 socket 另一端发送 FIN 包时,触发该事件。
5 timeout
当 socket 空闲超时时触发,仅是表明 socket 已经空闲。用户必须手动关闭连接。
6 drain
当写缓存为空得时候触发。可用来控制上传。
7 error
错误发生时触发。
8 close
当 socket 完全关闭时触发。参数 had_error 是布尔值,它表示是否因为传输错误导致 socket 关闭。
属性
1 socket.bufferSize
该属性显示了要写入缓冲区的字节数。
2 socket.remoteAddress
远程的 IP 地址字符串,例如:’74.125.127.100’ or ‘2001:4860:a005::68’。
3 socket.remoteFamily
远程IP协议族字符串,比如 ‘IPv4’ or ‘IPv6’。
4 socket.remotePort
远程端口,数字表示,例如:80 or 21。
5 socket.localAddress
网络连接绑定的本地接口 远程客户端正在连接的本地 IP 地址,字符串表示。例如,如果你在监听’0.0.0.0’而客户端连接在’192.168.1.1’,这个值就会是 ‘192.168.1.1’。
6 socket.localPort
本地端口地址,数字表示。例如:80 or 21。
7 socket.bytesRead
接收到得字节数。
8 socket.bytesWritten
发送的字节数。
Node.js DNS
Node.js Domain 模块
Node.js Domain(域) 简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的异常。引入 Domain 模块 语法格式如下:
var domain = require(“domain”)
web cat server.js var http = require(“http”);
var fs = require(“fs”);
var url = require(“url”);
http.createServer(function(request,response){ var pathname =
url.parse(request.url).pathname; console.log(“Request for”+pathname+”
received”); fs.readFile(pathname.substr(1),function(err,data){
if(err){ console.log(err);
response.writeHead(404,{‘Content-Type’:’text/html’}); }else{response.writeHead(200,{‘Content-Type’:’text/html’});
response.write(data.toString()); }
response.end();
}); }).listen(8888);
console.log(“Server is running at http://127.0.0.1:8888“)
cat client.js var http = require(“http”);
var options = { host:’localhost’, port:’8888’, path:”/index.htm”
};
var callback = function(response){
var body = ”;
response.on(‘data’,function(data){ body +=data;
});
response.on(‘end’,function(){ console.log(body); });
};
var req = http.request(options,callback); req.end();
Node.js Express 框架
yield 表达式
由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
遍历器对象的next方法的运行逻辑如下。
(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。