最好的JavaScript在线教程
在互联网发展的早期,JavaScript就已经成为支持网页内容交互体验的基础技术。随着时间推移,JavaScript业已升级成为互联网的核心技术。
长期以来,我都在学习JavaScript。学习JS一时爽,一直学习一直爽。
在学习过程中,接触很多学习资料,图书、视频等不一而足。
今天给大家介绍两个线上教程,都是广受好评的,相信你一定也看过。
1 Mozilla 开发者社区 JavaScript 教程
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
教程内容:
- 对于完全初学者
- JavaScript 第一步
- JavaScript 基本结构
- 介绍JavaScript 对象
- JavaScript 指南
- 中级内容
- 客户端 Web API
- 重新介绍 JavaScript(JS 教程)
- JavaScript 数据结构
- 如何使用比较操作符
- 闭包
- 高级内容
- 继承和原型链
- 严格模式
- JavaScript 类型数组
- 内存管理
- 并发模型以及事件循环
2 现代 JavaScript 教程
https://zh.javascript.info/
教程内容:
第 一 部分 JavaScript 编程语言
在这儿我们将从头开始学习 JavaScript,也会学习 OOP 等相关高级概念。
第 二 部分 浏览器:文档,事件,接口
学习如何管理浏览器页面:添加元素,操纵元素的大小和位置,动态创建接口并与访问者互动。
第 三 部分 其他文章
教程的前两部分未涉及的其他主题的内容列表。此处没有明确的层次结构,你可以按你需要的顺序阅读文章。
js代码解析:获取服务器数据并展示
<script>
const EXCHANGE_MAP = {
\’SHFE\’: 113,
\’DCE\’: 114,
\’CZCE\’: 115,
\’GFEX\’: 225,
\’INE\’: 142,
\’CFFEX\’: 220
};
async function fetchVarieties() {
try {
const response = await fetch(\’https://q.xxx.biz/\’);
const data = await response.json();
const groupedData = {};
data.list.forEach(item => {
const [exchange, code] = item.uid.split(\’|\’);
const variety = code.replace(/\\d+/g, \’\’);
if (!groupedData[exchange]) {
groupedData[exchange] = new Set();
}
groupedData[exchange].add({
code: variety,
name: item.name.replace(/\\d+/g, \’\’)
});
});
const select = document.getElementById(\’varietySelect\’);
Object.entries(groupedData).forEach(([exchange, varieties]) => {
const optgroup = document.createElement(\’optgroup\’);
optgroup.label = exchange;
varieties.forEach(variety => {
const option = document.createElement(\’option\’);
option.value = `${EXCHANGE_MAP[exchange]}_${variety.code}`;
option.textContent = variety.name;
optgroup.appendChild(option);
});
select.appendChild(optgroup);
});
} catch (error) {
console.error(\’Error fetching varieties:\’, error);
}
}
async function fetchContracts(variety) {
try {
const response = await fetch(`https://q.xxx.ink/redis?msgid=${variety}`);
const data = await response.json();
return data
.filter(item => /\\d+/.test(item.code))
.map(item => `${item.mktid}_${item.code}`);
} catch (error) {
console.error(\’Error fetching contracts:\’, error);
return [];
}
}
async function fetchPrices(contracts) {
try {
console.log(\’Fetching prices for contracts:\’, contracts);
const response = await fetch(`https://q.xxx.ink/custom/${contracts.join(\’,\’)}?orderBy=code&sort=asc&pageSize=100&pageIndex=0&callbackName=`);
const text = await response.text();
console.log(\’Raw response:\’, text);
const jsonStr = text.replace(/^[^({]*\\(|\\)[^}]*$/g, \’\’);
console.log(\’Processed JSON string:\’, jsonStr);
try {
const data = JSON.parse(jsonStr);
console.log(\’Parsed data:\’, data);
if (data && Array.isArray(data.list)) {
return data.list;
}
return [];
} catch (parseError) {
console.error(\’Error parsing JSON:\’, parseError);
console.log(\’Problematic JSON string:\’, jsonStr);
return [];
}
} catch (error) {
console.error(\’Error fetching prices:\’, error);
return [];
}
}
function updatePriceTable(prices) {
const tbody = document.querySelector(\’#priceData tbody\’);
tbody.innerHTML = \’\’;
if (!Array.isArray(prices) || prices.length === 0) {
const row = document.createElement(\’tr\’);
row.innerHTML = \'<td colspan=\”4\” style=\”text-align: center;\”>暂无数据</td>\’;
tbody.appendChild(row);
return;
}
prices.forEach(item => {
const row = document.createElement(\’tr\’);
row.innerHTML = `
<td>${item.name || \’-\’}</td>
<td>${item.p || \’-\’}</td>
<td>${item.zdf || \’-\’}%</td>
<td>${item.vol || 0}</td>
<td>${item.ccl || 0}</td>
`;
tbody.appendChild(row);
});
}
function sortContracts(prices) {
return prices.sort((a, b) => {
const monthA = a.name.match(/\\d+/)[0];
const monthB = b.name.match(/\\d+/)[0];
return monthA – monthB;
});
}
function updateChart(prices) {
const chartDom = document.getElementById(\’chartContainer\’);
const myChart = echarts.init(chartDom);
const sortedPrices = sortContracts(prices);
const option = {
title: {
text: \’月间合约对比\’,
left: \’center\’
},
tooltip: {
trigger: \’axis\’,
axisPointer: {
type: \’cross\’
}
},
legend: {
data: [\’价格\’, \’成交量\’, \’持仓量\’],
top: 30,
left: \’center\’
},
grid: [{
left: \’3%\’,
right: \’3%\’,
height: \’50%\’
}, {
left: \’3%\’,
right: \’3%\’,
top: \’65%\’,
height: \’25%\’
}],
xAxis: [{
type: \’category\’,
data: sortedPrices.map(item => item.name),
axisLine: { onZero: true },
grid: { top: \’50%\’ }
}, {
type: \’category\’,
gridIndex: 1,
data: sortedPrices.map(item => item.name),
position: \’bottom\’
}],
yAxis: [{
name: \’价格\’,
type: \’value\’,
splitLine: {
show: true
},
min: function (value) {
return value.min * 0.99; // 设置 Y 轴最小值为数据最小值的 0.9 倍
},
max: function (value) {
return value.max * 1.01; // 设置 Y 轴最大值为数据最大值的 1.1 倍
}
}, {
gridIndex: 1,
name: \’成交量/持仓量\’,
type: \’value\’,
splitLine: {
show: true
},
min: function (value) {
return value.min * 0.99; // 设置 Y 轴最小值为数据最小值的 0.9 倍
},
max: function (value) {
return value.max * 1.01; // 设置 Y 轴最大值为数据最大值的 1.1 倍
}
}],
series: [{
name: \’价格\’,
type: \’line\’,
data: sortedPrices.map(item => item.p || 0),
smooth: true,
lineStyle: {
width: 2
},
itemStyle: {
color: \’#5470c6\’
}
}, {
name: \’成交量\’,
type: \’bar\’,
xAxisIndex: 1,
yAxisIndex: 1,
data: sortedPrices.map(item => item.vol || 0),
itemStyle: {
color: \’#91cc75\’
}
}, {
name: \’持仓量\’,
type: \’bar\’,
xAxisIndex: 1,
yAxisIndex: 1,
data: sortedPrices.map(item => item.ccl || 0),
itemStyle: {
color: \’#fac858\’
}
}],
dataZoom: [{
type: \’inside\’,
xAxisIndex: [0, 1],
start: 0,
end: 100
}, {
show: true,
xAxisIndex: [0, 1],
type: \’slider\’,
bottom: 10,
start: 0,
end: 100
}]
};
myChart.setOption(option);
window.addEventListener(\’resize\’, () => {
myChart.resize();
});
}
document.getElementById(\’varietySelect\’).addEventListener(\’change\’, async (e) => {
const variety = e.target.value;
if (!variety) {
document.getElementById(\’contractList\’).textContent = \’\’;
updatePriceTable([]);
const chartDom = document.getElementById(\’chartContainer\’);
const myChart = echarts.init(chartDom);
myChart.clear();
return;
}
document.querySelector(\’.loading\’).style.display = \’block\’;
try {
const contracts = await fetchContracts(variety);
document.getElementById(\’contractList\’).textContent =
`[${contracts.map(c => c.split(\’_\’)[1]).join(\’,\’)}]`;
const prices = await fetchPrices(contracts);
updatePriceTable(prices);
if (prices && prices.length > 0) {
updateChart(prices);
}
} catch (error) {
console.error(\’Error updating data:\’, error);
document.getElementById(\’contractList\’).textContent = \’获取数据失败\’;
updatePriceTable([]);
} finally {
document.querySelector(\’.loading\’).style.display = \’none\’;
}
});
// 从URL中获取默认品种
(async function() {
const urlParams = new URLSearchParams(window.location.search);
const defaultVariety = urlParams.get(\’variety\’);
if (defaultVariety) {
document.getElementById(\’varietySelect\’).value = defaultVariety;
await fetchContracts(defaultVariety);
const contracts = await fetchContracts(defaultVariety);
document.getElementById(\’contractList\’).textContent =
`[${contracts.map(c => c.split(\’_\’)[1]).join(\’,\’)}]`;
const prices = await fetchPrices(contracts);
updatePriceTable(prices);
if (prices && prices.length > 0) {
updateChart(prices);
}
} else {
await fetchVarieties();
}
})();
</script>
这段代码涉及到了很多JavaScript的知识点,以下是一些主要的知识点:
1. 变量和常量
●使用const声明常量,例如EXCHANGE_MAP。
●变量的解构赋值,如const [exchange, code] = item.uid.split(\’|\’);。
2. 数据结构
●使用对象({})和Map进行数据存储和检索。
●使用Set来存储唯一值。
3. 异步编程
●使用async/await进行异步操作,简化Promise的使用。
●使用fetchAPI进行网络请求。
4. 数组和字符串方法
●数组的forEach、map、filter等方法。
●字符串的split、replace、match等方法。
5. DOM操作
●使用document.getElementById、document.createElement等方法操作DOM。
●使用appendChild方法添加子元素。
6. 事件处理
●使用addEventListener为DOM元素添加事件监听器。
7. 错误处理
●使用try…catch语句进行错误捕获和处理。
8. JSON处理
●使用JSON.parse解析JSON字符串。
●处理JSON解析错误。
9. 正则表达式
●使用正则表达式进行字符串匹配和替换,如/\\d+/g。
10. 排序
●使用数组的sort方法进行排序。
11. ECharts库
●使用ECharts库进行数据可视化,包括图表的配置和更新。
12. 模块化
●代码结构体现了模块化的思想,将不同的功能封装在不同的函数中。
13. 立即执行函数表达式(IIFE)
●使用IIFE来封装一些初始化代码,避免污染全局作用域。
14. URL和查询参数处理
●使用URLSearchParams处理URL查询参数。
15. 条件渲染
●根据数据是否存在来决定渲染内容,例如在没有数据时显示“暂无数据”。
这些知识点覆盖了JavaScript的基础语法、异步编程、DOM操作、数据处理和可视化等多个方面,展示了现代JavaScript开发的综合应用。
JavaScript代码的三种引入方式【操作演示】
在网页中编写JavaScript代码时,需要先引入JavaScript代码。JavaScript代码有3种引入方式,分别是行内式、嵌入式和外链式,下面分别进行讲解。
行内式是将JavaScript代码作为HTML标签的属性值使用。例如,在单击超链接“test”时,弹出一个警告框提示“Hello”,示例代码如下:
需要说明的是,行内式只有在临时测试或者特殊情况下使用,一般情况下不推荐使用行内式,因为行内式有如下缺点。
(1)行内式可读性较差,尤其是在HTML文件中编写大量JavaScript代码时,不方便阅读。
(2)行内式在遇到多层引号嵌套的情况时,引号非常容易混淆,导致代码出错。
嵌入式(或称内嵌式)使用<scrip>标签包裹JavaScript代码,直接编写到HTML文件中,通常将其放到<head>标签<body>或标签中。<scrip>标签的type属性用于告知浏览器脚本类型,HTML.5中该属性的默认值为“text/javascript”,因此在使用HTML5时可以省略ype属性。嵌入式的示例代码如下:
外链式(或称外部式)是将JavaScript 代码写在一个单独的文件中,一般使用“js”作为文件的扩展名,在HTML页面中使用<script>标签的src属性引人“js”文件。外链式适合javascript代码量较多的情况。在html页面中引入“js”文件,示例代码如下:
上述代码表示引入当前目录下的tesL.js文件。需要注意的是,外链式的标签内不可以编写JavaScript 代码。
为了帮助初学者更好地理解外链式,下面利用外链式实现浏览网页时在页面中自动弹出警告框。创建Example02.html文件,引入Example02.js文件,具体代码如例1-2所示。
标签的src属性设置了要引入的文件为Example02.js。
创建Example02.js文件,在该文件中编写如下代码:
保存代码,在浏览器中访问Example02.html文件,页面效果与例1-1相同。
以上讲解了JavaScript的3种引入方式。现代网页开发中提倡结构、样式、行为的分离,即分离HTML、CSS、JavaScrixt这3部分代码,这样更有利于文件的维护。当需要编写大量的、逻辑复杂的、具有特定功能的JavaScrigt代码时,推荐使用外链式。外链式相比嵌入式,具有以下3点优势:
(1)外链式存在于独立文件中,有利于修改和维护,而嵌人式会导致HTML代码与JavaScript代码混合在一起。
(2)外链式可以利用浏览器缓存提高速度。例如,在多个页面中引入相同的JavaScript文件时,打开第1个页面后,浏览器将JavaScript文件缓存下来,下次打开其他页面时就不用重新下载该文件了。
(3)外链式有利于HTML页h代码结构化,把大段的JavaScript代码分离到HTML页面之外,既美观,也方便文件级别的代码复用。
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。