标签归档:javascript

Node 生态落后了吗?

这两年我越来越明显地感觉到:

有些新工具,真的在把“开发”这件事重新变简单。

比如 Go,很多时候直接就是:

go run .

Python 这边有了 uv 之后,也越来越像这样:

uv run app.py

但回到 Node 世界,常见操作还是:

pnpm install
pnpm dev

于是很容易让人产生一个问题:

Node 生态是不是有点落后了?

我的答案是:

不是落后在能力上,而是落后在默认体验上。

Node 的问题,不是不能做,而是太碎了

Node 当然不是做不到“一条命令启动”。

它也有很多办法:

  • npx
  • npm exec
  • pnpm dlx
  • 各种 create-* 脚手架
  • 再加上 Bun 这种更激进的一体化方案

但问题是,Node 这些能力长期都分散在不同层里:

  • node 负责运行
  • npm/pnpm 负责装包
  • package.json scripts 负责命令入口
  • tsc/tsx/vite/webpack 负责构建或转译
  • next/vite/nuxt 再往上包一层

每一层都没问题,叠起来就会让人觉得麻烦。

相比之下,Go 和 uv 给人的感觉更直接:

我不用先理解这个生态的历史,只要先跑起来就行。

为什么 Node 会这样?

说白了,还是历史包袱。

Node 生态起得太早,先解决的是“怎么把生态做大”,不是“怎么让默认体验最统一”。

所以它天然就更强调:

  • 灵活
  • 可组合
  • 社区工具自由竞争

这带来了巨大的繁荣,但也带来了一个副作用:

入口太多,约定太多,心智负担太重。

尤其是前端项目,很多复杂度还不是 Node 自己一个人的锅。

它还要处理:

  • TypeScript
  • 浏览器兼容
  • 打包
  • 热更新
  • SSR / CSR
  • 静态资源
  • 各种框架约定

所以 Node 的“重”,一半是历史问题,一半是场景本来就复杂。

Go 和 uv 为什么会显得更现代?

不是因为它们“技术上碾压 Node”。

而是因为它们把最常见的路径做得更短。

你不需要先想:

  • 要不要先装依赖
  • 用哪个包管理器
  • 是不是还要配 TS
  • 入口命令到底在哪

而是直接先跑。

这件事看着小,但体验差别很大。

现在很多开发者真正喜欢的,不是工具更强,而是工具更少打扰自己。

Node 还行不行?

当然行,而且很多场景里还是最强。

尤其你只要在做这些事:

  • React
  • Next.js
  • Vite
  • 前端工程化
  • 组件库
  • Web 全栈

Node 生态还是最成熟、最完整、最难绕开的那一个。

所以问题从来不是 Node 不行。

而是:

它已经是最大生态了,但默认体验还是不够干净。

我的判断

如果只用一句话总结:

Node 没有落后在生态能力上,但在“开箱即用的现代工具链体验”上,确实显得老了。

Go 和 uv 让人觉得舒服,不只是因为快,而是因为它们更像现代工具:

  • 常用路径短
  • 官方入口清晰
  • 不需要先理解太多背景

Node 更像一个特别繁荣的大城市,什么都有,但路有点绕。

Go 和 uv 更像新城区,规划更清楚。

未来我觉得 Node 不会输,但 Bun、Deno、uv 这些新工具,肯定会继续逼着整个生态往更简单、更统一的方向走。

这对开发者来说是好事。

因为我们真正想要的,从来不是工具有多复杂,而是:

能不能赶紧开始写代码。

JavaScript引用

JavaScript的一个重要的方面是引用的概念。引用就是指向对象实际位置的指针。这是一项极其强大的功能。前提是,实际的对象决不是一个引用:字符串总是一个字符串,数组总是一个数组。然而,多个变量可以引用相同的对象。JavaScript就是以这种引用机制为基础。通过维护一系列的指向其他对象的引用,语言为你提供了更大的弹性。
当几个变量指向相同对象时,修改这个对象会在所有指向这个对象的变量上有什么反应呢?

var obj = new Object();
var objRef = obj;
obj.someProp = true;
console.log(objRef===obj); // true
var arr = new Array(1,2);
var arrRef = arr;
arr.push(3);
console.log(arr === arrRef); // true
var str = "test";
var strRef = str;
str += "ing";
console.log(str === strRef); // false
var num = 1;
var numRef = num;
num += 1;
console.log(num === numRef); // false
var boo = true;
var booRef = boo;
boo = !boo;
console.log(boo === booRef); // false

我们知道string, number, bool是JavaScript的基础类型,Object, Array是组合类型,组合类型的值是以对象的属性存储的,所以改变了一个变量的值,所有指向它的变量都会变。

JavaScript类型转换 type conversions

var a = new Boolean(false);
console.log(a);//{}
console.log(a == false)//true
console.log(a === false)//false
if(a){
    console.log("new Boolean(false) is true")//new Boolean(false) is true
}else{
    console.log("new Boolean(false) is false")
}

这里a转换为true,因为a是一个Boolean的object,而object如果不是null或者undefined,就会被转换为true
这里主要需要分清楚值类型(primitive)和对象类型(object)
下面是JavaScript类型转换

JavaScript type conversions
转换为:
String Number Boolean Object
undefined "undefined" NaN false throws TypeError
null "null" 0 false throws TypeError
true "true" 1

new Boolean(true)

false

"false"

0

new Boolean(false)

""?(empty string)

0

false

new String("")

"1.2"?(nonempty, numeric)

1.2

true

new String("1.2")

"one"?(nonempty, non-numeric)

NaN

true

new String("one")

0

"0"

false

new Number(0)

-0

"0"

false

new Number(-0)

NaN

"NaN"

false

new Number(NaN)

Infinity

"Infinity"

true

new Number(Infinity)

-Infinity

"-Infinity"

true

new Number(-Infinity)

1?(finite, non-zero)

"1"

true

new Number(1)

{}?(any object)

true

[]?(empty array)

""

0

true

[9]?(1 numeric elt)

"9"

9

true

['a']?(any other array)

use join() method

NaN

true

function(){}?(any function)

NaN true

javascript:null and undefined

声明而没有赋值的变量是undefined
没有返回值的函数返回的是undefined

var a;//undefined
console.log(a);//undefined
console.log(typeof a);//undefined
console.log(typeof a == undefined)//false
console.log(typeof a == "undefined")//true
console.log(typeof a === undefined)//false
console.log(typeof a === "undefined")//true
console.log(a==null);//true
console.log(a==undefined);//true
console.log(a===null);//false
console.log(a===undefined);//true
console.log("*******************");
var b = null;//null
console.log(b);//null
console.log(typeof b);//object
console.log(typeof b == undefined)//false
console.log(typeof b == "undefined")//false
console.log(typeof b === undefined)//false
console.log(typeof b === "undefined")//false
console.log(b==null);//true
console.log(b==undefined);//true
console.log(b===null);//true
console.log(b===undefined);//false

JS operations on JSON summary

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式。同时,JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包。
本文主要是对JS操作JSON的要领做下总结。
在JSON中,有两种结构:对象和数组。

  1. 一个对象以{(左括号)开始,}(右括号)结束。每个“名称”后跟一个:(冒号);“‘名称/值’ 对”之间运用 ,(逗号)分隔。 名称用引号括起来;值如果是字符串则必须用括号,数值型则不须要。例如:
    var o = {
      "xlid": "cxh",
      "xldigitid": 123456,
      "topscore": 2000,
      "topplaytime": "2009-08-20"
    }
    
  2. 数组是值(value)的有序集合。一个数组以[(左中括号)开始,](右中括号)结束。值之间运用 ,(逗号)分隔。例如:
    var jsonranklist = [{
      "xlid": "cxh",
      "xldigitid": 123456,
      "topscore": 2000,
      "topplaytime": "2009-08-20"
    }, {
      "xlid": "zd",
      "xldigitid": 123456,
      "topscore": 1500,
      "topplaytime": "2009-11-20"
    }];
    

为了方便地处理JSON数据,JSON提供了json.js包,下载地址:http://www.json.org/json.js
在数据传输流程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键。例如:

  • JSON字符串:
    var str1 = '{ "name": "cxh", "sex": "man" }';
    
  • JSON对象:
    var str2 = { "name": "cxh", "sex": "man" };
    
  1. JSON字符串转换为JSON对象,要运用上面的str1,必须运用下面的要领先转化为JSON对象:
    var obj = eval('(' + str + ')');//由JSON字符串转换为JSON对象
    

    或者

    var obj = str.parseJSON(); //由JSON字符串转换为JSON对象
    

    或者

    var obj = JSON.parse(str); //由JSON字符串转换为JSON对象
    

    然后,就可以这样读取:

    Alert(obj.name);
    Alert(obj.sex);
    

    特别留心:如果obj本来就是一个JSON对象,那么运用 eval()函数转换后(哪怕是多次转换)还是JSON对象,但是运用 parseJSON()函数处理后会有疑问(抛出语法异常)。

  2. 可以运用 toJSONString()或者全局要领 JSON.stringify()将JSON对象转化为JSON字符串。
    例如:

    var last=obj.toJSONString(); //将JSON对象转化为JSON字符
    

    或者

    var last=JSON.stringify(obj); //将JSON对象转化为JSON字符
    
    alert(last);
    

    留心:上面的多个要领中,除了eval()函数是js自带的之外,其他的多个要领都来自json.js包。新版本的 JSON 修改了 API,将 JSON.stringify()JSON.parse() 两个要领都注入到了 Javascript 的内建对象里面,前者变成了 Object.toJSONString(),而后者变成了 String.parseJSON()。如果提示找不到toJSONString()parseJSON()要领,则说明您的json包版本太低。

html+js轮播图片slide show