每日两题 T21
算法
LeetCode T151. 翻转字符串里的单词[1]
描述
给定一个字符串,逐个翻转字符串中的每个单词。
示例1
输入: "the sky is blue"
输出: "blue is sky the"
示例2
输入: " hello world! "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例3
输入: "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
代码
/**
* @param {string} s
* @return {string}
*/
var reverseWords = function(s) {
return s.split(' ').filter(item => item).reverse().join(' ')
};
前端
介绍下 npm 模块安装机制
npm 模块安装机制:
•敲击npm install
命令•查询node_modules目录之中是否已经存在指定模块
•若存在,不再重新安装•若不存在
•npm 向 registry 查询模块压缩包的网址•下载压缩包,存放在根目录下的.npm
目录里•解压压缩包到当前项目的node_modules
目录
执行 preinstall
preinstall 钩子此时会执行。
确定依赖模块
确定工程中的首层依赖——dependencies 和 devDependencies中指定的模块
以工程本身为依赖树根节点,此时会多进程深入遍历节点
获取模块
•获取模块信息。确定版本,因为 package.json 中往往是 semantic version(semver,语义化版本)。此时如果版本描述文件(npm-shrinkwrap.json 或 package-lock.json)中有该模块信息,则已之为准,如果没有则从仓库获取。如 packaeg.json 中某个包的版本是 ^1.1.0,则会获取符合 1.x.x 形式的最新版•获取模块实体。上一步获取了压缩包地址(resolved 字段),npm 会以此地址检查本地缓存,若有就直接拷贝,没有则从仓库下载•查找模块依赖,若有依赖则返回第1步,若没有则停止。
模块扁平(dedupe)
上一步获取到的依赖树,需要清除重复模块。比如 A 模块依赖于 moment
,B 模块也依赖 moment
。在 npm3
以前会严格按照依赖树的结构进行安装,会造成模块冗余。
从 npm3
开始默认加入了一个 dedupe 的过程。它会遍历所有节点,逐个将模块放在根节点下面,也就是 node-modules 的第一层。当发现有重复模块时,则将其丢弃。
这里需要对重复模块进行一个定义,它指的是模块名相同且 semver 兼容。每个 semver 都对应一段版本允许范围,如果两个模块的版本允许范围存在交集,那么就可以得到一个兼容版本,而不必版本号完全一致,这可以使更多冗余模块在 dedupe 过程中被去掉。
举个例子,假设一个依赖树原本是这样:
node_modules
-- foo
---- lodash@version1
假设 version1 和 version2 是兼容版本,则经过 dedupe 会成为下面的形式:
node_modules
-- foo
-- bar
-- lodash(保留的版本为兼容版本)
假设 version1 和 version2 为非兼容版本,则后面的版本保留在依赖树中:
node_modules
-- foo
-- lodash@version1
-- bar
---- lodash@version2
安装模块
更新工程中的 node_modules
,并执行模块中的生命周期函数(preinstall
、install
、postinstall
)。
执行工程自身生命周期
当前 npm 工程如果定义了钩子此时会被执行(按照 install
、postinstall
、prepublish
、prepare
的顺序)。
生成或更新版本描述文件,npm install
过程完成。
References
[1]
151. 翻转字符串里的单词: https://leetcode-cn.com/problems/reverse-words-in-a-string/
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 简单谈谈Linux内核定时器
- Ubuntu cron日志开启与查看的实现步骤
- 详解Apache配置多个监听端口和不同的网站目录
- CentOS7服务器中apache、php7以及mysql5.7的安装配置代码
- Ubuntu中静态DNS配置的方法详解
- shiro缓存机实例代码
- Linux deepin 删除多余内核的实现方法
- linux烧写、配置、搭建Edison环境
- 详解使用 split 命令分割 Linux 文件
- 在博客后台为内容模块实现增删改查功能
- 解决Debian系统自动更新软件包的问题的方法
- PHP 基于 Cookie + Session 实现用户认证功能
- 创建并运行一个新的 Laravel 项目
- linux nslookup命令使用详解
- Go 数据存储篇(五):建立数据库连接并进行增删改查操作