一、数组对比
1. 基本声明和初始化
Perl:
# 声明数组
my @array = (1, 2, 3);
my @empty = (); # 空数组
# 数组引用
my $array_ref = [1, 2, 3]; # 匿名数组引用
# 多维数组
my @matrix = (
[1, 2, 3],
[4, 5, 6],
);
JavaScript:
// 声明数组
let array = [1, 2, 3];
let empty = []; // 空数组
// 数组引用(直接就是引用)
let arrayRef = [1, 2, 3];
// 多维数组
let matrix = [
[1, 2, 3],
[4, 5, 6]
];
2. 数组操作
索引和访问:
# Perl - 索引从0开始
$array[0] = 10; # 标量上下文用$
$last = $array[-1]; # 负索引支持
// JavaScript
array[0] = 10;
let last = array[array.length - 1];
let last2 = array.at(-1); // ES2022支持负索引
数组大小:
# Perl
my $size = @array; # 标量上下文获取数组长度
my $last_index = $#array; # 最后一个索引
// JavaScript
let size = array.length; // 属性,不是方法
3. 数组方法/函数
Perl数组函数:
# 添加/删除元素
push @array, 4; # 末尾添加
pop @array; # 删除末尾
unshift @array, 0; # 开头添加
shift @array; # 删除开头
# 切片
my @slice = @array[1..3]; # 范围操作符
# 排序
my @sorted = sort @array;
# 反转
my @reversed = reverse @array;
# 合并
my @merged = (@array1, @array2);
JavaScript数组方法:
// 添加/删除
array.push(4); // 末尾添加
array.pop(); // 删除末尾
array.unshift(0); // 开头添加
array.shift(); // 删除开头
// 切片
let slice = array.slice(1, 4);
// 排序
let sorted = array.sort((a, b) => a - b);
// 反转
let reversed = array.reverse();
// 合并
let merged = [...array1, ...array2];
// 现代方法(Perl没有直接对应的)
array.forEach(item => console.log(item));
let mapped = array.map(x => x * 2);
let filtered = array.filter(x => x > 2);
let reduced = array.reduce((sum, x) => sum + x, 0);
二、哈希(Perl) vs 对象(JavaScript)
1. 声明和初始化
Perl哈希:
# 哈希声明
my %hash = (
'name' => 'John',
'age' => 30,
'city' => 'NYC'
);
# 简写(键会自动加引号)
my %hash2 = (
name => 'John', # 自动引用
age => 30,
);
# 空哈希
my %empty = ();
# 哈希引用
my $hash_ref = {
name => 'John',
age => 30,
};
JavaScript对象:
// 对象声明
let obj = {
name: 'John',
age: 30,
'city': 'NYC' // 键名可以用引号
};
// 空对象
let empty = {};
// ES6计算属性名
let key = 'dynamicKey';
let obj2 = {
[key]: 'value',
['computed']: 'value2'
};
2. 访问和操作
访问值:
# Perl
my $name = $hash{'name'}; # 使用大括号
$hash{'age'} = 31; # 赋值
# 使用变量作为键
my $key = 'name';
my $value = $hash{$key};
# 删除键
delete $hash{'city'};
// JavaScript
let name = obj.name; // 点表示法
let age = obj['age']; // 括号表示法
// 变量作为键
let key = 'name';
let value = obj[key];
// 删除属性
delete obj.city;
// ES6动态属性名
obj[key] = 'new value';
检查键存在:
# Perl
if (exists $hash{'name'}) {
print "Key exists\n";
}
// JavaScript
if ('name' in obj) {
console.log('Property exists');
}
if (obj.hasOwnProperty('name')) {
console.log('Own property exists');
}
3. 遍历
Perl哈希遍历:
# 遍历键
foreach my $key (keys %hash) {
print "$key: $hash{$key}\n";
}
# 遍历值
foreach my $value (values %hash) {
print "$value\n";
}
# 同时遍历键值对
while (my ($key, $value) = each %hash) {
print "$key => $value\n";
}
JavaScript对象遍历:
// 遍历键
for (let key in obj) {
console.log(`${key}: ${obj[key]}`);
}
// ES6方法
Object.keys(obj).forEach(key => {
console.log(`${key}: ${obj[key]}`);
});
// 遍历值
Object.values(obj).forEach(value => {
console.log(value);
});
// 遍历键值对
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});
三、重要差异和特性对比
1. 数据类型差异
| 特性 |
Perl |
JavaScript |
|---|
| 数组变量符号 |
@前缀 |
无特殊符号 |
| 哈希变量符号 |
%前缀 |
无特殊符号 |
| 标量引用符号 |
$前缀 |
无特殊符号 |
| 上下文概念 |
强(列表/标量) |
无 |
| 负索引 |
原生支持 |
ES2022的at()方法 |
| 自动展开 |
在列表上下文中 |
需要展开运算符... |
2. 引用和复制
Perl:
# 数组引用(需要显式引用)
my $ref = \@array; # 引用
my @deref = @{$ref}; # 解引用
# 深度复制
use Storable qw(dclone);
my $deep_copy = dclone($complex_ref);
JavaScript:
// 数组/对象本身就是引用
let ref = array; // 引用同一数组
let shallowCopy = [...array]; // 浅拷贝
let objCopy = {...obj}; // 对象浅拷贝
// 深度复制
let deepCopy = JSON.parse(JSON.stringify(obj)); // 简单方法
// 或使用 structuredClone()(现代浏览器)
3. 特殊特性
Perl特殊数组操作:
# 范围操作符创建数组
my @numbers = 1..10;
# 数组切片
my @subset = @array[0, 2, 4..6];
# 数组作为栈/队列
push @stack, $item;
$item = pop @stack;
JavaScript特殊特性:
// 数组解构
let [first, second, ...rest] = array;
// 对象解构
let {name, age} = obj;
// 动态属性名
let dynamicKey = 'prop';
let obj = {
[dynamicKey + 'Name']: 'value'
};
// 原型链(Perl没有对应概念)
let parent = {x: 1};
let child = Object.create(parent);
child.y = 2;
四、性能和使用场景建议
性能考虑:
Perl数组:内存连续,访问快速,但插入/删除可能较慢
JavaScript数组:动态数组实现,方法丰富,V8等引擎优化良好
Perl哈希:查找速度快(哈希表),适合大量数据
JavaScript对象:类似哈希表,但原型链增加查找开销
使用建议:
- Perl适合:文本处理、系统脚本、传统CGI编程
- JavaScript适合:Web开发、前后端统一、现代应用开发
- 数组选择:Perl在文本处理中数组操作更简洁,JS在现代应用中有更丰富的方法
- 哈希/对象:Perl哈希更适合传统数据处理,JS对象更灵活且有现代特性
五、转换示例
Perl数据结构转JSON:
use JSON;
my $perl_hash = { users => [{name => 'John'}, {name => 'Jane'}] };
my $json = encode_json($perl_hash);
JavaScript对象转Perl结构:
// JS中构建类似Perl的数据结构
let data = {
users: [
{name: 'John', age: 30},
{name: 'Jane', age: 25}
]
};
// 发送到Perl后端
fetch('/api', {
method: 'POST',
body: JSON.stringify(data)
});
这种对比显示了两种语言在数据处理理念上的差异:Perl更加面向文本和系统编程,语法简洁但特殊符号多;JavaScript更现代,语法一致且功能丰富,特别适合Web和异步编程环境。