亚灿网志 - JS
type: channel
link: https://blog.manyacan.com/tag/JS/
items: 「GDIImputer」开发技术文档
items: 「Typecho」博客系统的美化与优化
items: 「JS高级」ES6
items: 「JS高级」构造函数和原型

「GDIImputer」开发技术文档
type: item
date: 2024-11-23T10:33:00+08:00
description: 项目概述DataImputer 是一个基于 Web 的Water Supply Systems数据修补系统。采用图傅里叶变换原理，针对供水管网的流量、压力时间序列进行数据修补工作。方法论部分请参考论文：ZHOU X, MAN Y, LIU S, et al. 2024. Leveraging multi-level correlations for imputing monitoring data in water supply systems using graph signal sampling theory. Water Research X [J], 25: 100274.项目地址为：https://group.zhouxiao.tech/imputation.html主要功能为允许用户上传含有缺失值的供水管网流量、压力数据文件，进行自动化的数据修补工作。系统能够对缺失的数据进行插补，并在处理完成后生成图表以可视化结果，支持下载处理后的文件。该系统设计成全自动化流程，简化用户操作，提高数据预处理效率。系统架构项目实现过程中，核心包括前端页面设计、后端数据处理逻辑、跨域处理以及服务器配置优化。主要技术栈为：前端页面和交互逻辑主要由 HTML、CSS、JavaScript 和 jQuery 组成；后端由 Flask 提供 API 支持，包括文件上传、数据处理、图表生成和文件下载；数据处理基于 Pandas 和 NumPy 实现；图表使用 pyecharts 生成；通过 AJAX 技术进行前后端通信。前端设计前端核心框架结构为： 1. 上传文件 2. 运行算法 3. 保存文件 主要分为三部分：上部显示区域：用于显示可交互图表；操作区域：主要是三个按钮（1. 上传文件、2. 运行算法、3. 保存文件）；底部消息框：为用户展示前后端反馈消息。主要样式如下所示：成品展示前端部分技术不需要详细阐述，有问题直接 F12 控制台查看源代码。有一个设计点需要注意：考虑到用户上传的时间序列可能比较长，且大部分研究者日常工作都会使用PC进行访问本网站，因此 的宽度要尽量宽，而不是局限于父类元素的100%，这里采用的是绝对定位的方法将其与父元素居中的同时，宽度可以达到：@media (min-width: 800px) { #display-area { width: 90vw; } }这样就完美地同时顾及了页面设计美学和用户体验。JS工具函数COOKIE设置相关函数首先介绍几个主要的COOKIE工具函数，首先是设置Cookie和读取Cookie的函数：// 设置 Cookie 的函数 function setCookie(name, value, hours) { const date = new Date(); date.setTime(date.getTime() + (hours * 60 * 60 * 1000)); // 设置过期时间 document.cookie = `${name}=${value}; expires=${date.toUTCString()}; path=/`; } // 获取 Cookie 的函数 function getCookie(name) { const cookieArr = document.cookie.split("; "); for (let i = 0; i < cookieArr.length; i++) { const cookiePair = cookieArr[i].split("="); if (name === cookiePair[0]) { return decodeURIComponent(cookiePair[1]); } } return null; }然后是每次刷新页面或者第一次进入页面的恢复函数：function restorePreviousUpload() { const savedFilename = getCookie('uploadedFilename'); if (savedFilename) { $('#control-buttons').attr('data-filename', savedFilename); // 发送 AJAX 请求，让后端检查是否存在该文件并处理 $.ajax({ url: 'https://impute.zhouxiao.tech/upload', // 与后端的上传和检查接口一致 type: 'POST', data: { filename: savedFilename }, // 仅发送文件名，后端将根据文件名查找文件 success: function (response) { const message = ` …

「Typecho」博客系统的美化与优化
type: item
date: 2022-09-15T17:30:00+08:00
description: 每次更改或新增代码后，一定要及时查看控制台是否有报错，使用PC和移动端多次访问确保无误！！！网站设置网站后台设置基于宝塔面板。备份设置需要备份的东西都直接在宝塔后台备份就行，备份网站程序和数据库两个压缩包文件就行了。如果重装网站后更改了数据库账号密码，那么就直接在Typecho程序根目录下的config.inc.php文件中第56行更改数据库连接设置就行了：/** 定义数据库参数 */ $db->addServer(array ( 'host' => 'localhost', 'user' => '****', 'password' => '******', 'charset' => 'utf8', 'port' => '*******', 'database' => '******', ), Typecho_Db::READ | Typecho_Db::WRITE);网站所有都调整完毕后，可以在宝塔后台安装七牛云官方备份程序：可以自动将程序备份至七牛云账户。伪静态设置在宝塔网站设置中添加伪静态规则：if (!-e $request_filename) { rewrite ^(.*)$ /index.php$1 last; }然后在Typecho后台设置地址重写：CDN加速将主题下的assets文件夹全部复制至七牛云CDN，使用CDN加速全部主题资源。本站主题资源assets资源已全部放入七牛云CDN，如果需要进行文件修改，修改后需要在七牛云CDN中的刷新预取中刷新文件链接才会完成文件更新。使用自制404页面在宝塔后台打开网站配置文件，取消注释第28行：#ERROR-PAGE-START 错误页配置，可以注释、删除或修改 error_page 404 /404.html;然后在站点根目录重写404.html。流量限制后台登陆加密SQL语句学习将cid=1651的文章评论全部转移至cid=1561的文章下面：update typecho_comments set cid=1561 where cid=1651;在typecho_contents表中选择cid=1390的文章：SELECT * FROM `typecho_contents` WHERE cid=1390;插件设置ExSearch第一次使用该插件需要重建索引。该插件中不能引入JQuery，因为在主题中已经引入，如果再次引入，博客主页会出现空白。Meting问题：网易云歌单只能解析第一首歌曲，网易云无论是自己收藏的歌单还是公开歌单，均只能获取第一首，歌手与专辑正常。解决方案：插件后台填写网易云音乐Cookie。获取方法：打开 https://music.163.com/ ，F12-网络-再次刷新找到 music.163.com项，点击进去找到 cookie的值复制。如果网站开启PJAX局部刷新，需要设置重载函数：loadMeting(); // 跳转页面后重新解析播放器 if (typeof aplayers !== 'undefined') { // 跳转页面后暂停播放 for (var i = 0; i < aplayers.length; i++) { try { aplayers[i].destroy() } catch (e) {} } }解决（APlayer-Typecho）插件失效问题：可以通过替换插件中的include/Meting.php解决。访问地址：https://github.com/metowolf/Meting，然后复制src/Meting.php代码到插件中QQ音乐即可恢复。原因是插件中的Meting版本为（1.5.2）太过老旧，更换为最新的Meting（1.5.11）即可。音乐播放提示：// Meting 音乐播放提示 $('.aplayer-body').each(function () { // 单曲模块播放 $(this).find('div.aplayer-pic').click(function () { let songTitle = $(this).next().find('.aplayer-title').text(), songAuthor = $(this).next().find('.aplayer-author').text(); if (!$(this).find("*").eq(0).hasClass('aplayer-play')) { VOID.alert('开始播放' + songAuthor + '的《' + songTitle + '》~') } else { VOID.alert('音乐已暂停~') } }) // 歌单列表播放模块 $(this).next().find('ol>li').cli…

「JS高级」ES6
type: item
date: 2017-09-29T18:37:00+08:00
description: ES6相关概念（★★）什么是ES6ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。版本更新为什么使用 ES6 ?每一次标准的诞生都意味着语言的完善，功能的加强。JavaScript语言本身也有一些令人不满意的地方。变量提升特性增加了程序运行时的不可预测性；语法过于松散，实现相同的功能，不同的人可能会写出不同的代码。ES6新增语法let（★★★）ES6中新增了用于声明变量的关键字let声明的变量只在所处于的块级有效 if (true) { let a = 10; } console.log(a) // a is not defined注意：使用let关键字声明的变量才具有块级作用域，使用var声明的变量不具备块级作用域特性。不存在变量提升console.log(a); // a is not defined let a = 20;暂时性死区利用let声明的变量会绑定在这个块级作用域，不会受外界的影响 var tmp = 123; if (true) { tmp = 'abc'; let tmp; } console.log(tmp)经典面试题 var arr = []; for (var i = 0; i < 2; i++) { arr[i] = function () { console.log(i); } } arr[0](); // 2 arr[1](); // 2经典面试题图解：此题的关键点在于变量i是全局的，函数执行时输出的都是全局作用域下的i值。 let arr = []; for (let i = 0; i < 2; i++) { arr[i] = function () { console.log(i); } } arr[0](); // 0 arr[1](); // 1经典面试题图解：此题的关键点在于每次循环都会产生一个块级作用域，每个块级作用域中的变量都是不同的，函数执行时输出的是自己上一级（循环产生的块级作用域）作用域下的i值.小结let关键字就是用来声明变量的使用let关键字声明的变量具有块级作用域在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的防止循环变量变成全局变量使用let关键字声明的变量没有变量提升使用let关键字声明的变量具有暂时性死区特性代码：/* --------let关键字就是用来声明变量的-------- */ // let a = 10; // console.log(a); /* --------使用let关键字声明的变量具有块级作用域-------- */ // if (true) { // let b = 20; // console.log(b) // if (true) { // let c = 30; // } // console.log(c); // } // console.log(b) /* -------在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的--------- */ if (true) { let num = 100; var abc = 200; } console.log(abc); console.log(num) /* -------防止循环变量变成全局变量--------- */ for (let i = 0; i < 2; i++) {} console.log(i); /*-----使用let关键字声明的变量没有变量提升------*/ console.log(a); // a is not defined let a = 100; /* -------使用let关键字声明的变量具有暂时性死区特性------- */ var num = 10 if (true) { console.log(num); // num不会对外部进行查找 // num is not defined let num = 20; }const（★★★）声明常量，常量就是值（内存地址）不能变化的量具有块级作用域 if (true) { const a = 10; if (true) { const a = 20; console.log(a); // 20 } console.log(a); // 10 } console.log(a) // a is not defined声明常量时必须赋值const PI; // Missing initializer in const declaration常量赋值后，值不能修改const PI = 3.14; PI = 100; // Assignment to constant va…

「JS高级」构造函数和原型
type: item
date: 2017-09-22T18:37:00+08:00
description: 1.构造函数和原型1.1对象的三种创建方式--复习1、字面量方式：var obj = {};2、new关键字：var obj = new Object();3、构造函数方式function Person(name,age){ this.name = name; this.age = age; } var obj = new Person('zs',12);1.2静态成员和实例成员1.2.1实例成员实例成员就是构造函数内部通过this添加的成员，如下列代码中uname、age、sing就是实例成员，实例成员只能通过实例化的对象来访问： function Star(uname, age) { this.uname = uname; this.age = age; this.sing = function() { console.log('我会唱歌'); } } var ldh = new Star('刘德华', 18); console.log(ldh.uname);//实例成员只能通过实例化的对象来访问1.2.2静态成员静态成员是指在构造函数本身上添加的成员，如下列代码中sex就是静态成员，静态成员只能通过构造函数来访问： function Star(uname, age) { this.uname = uname; //实例成员就是构造函数内部通过this添加的成员 uname age sing 都是实例化成员 this.age = age; this.sing = function() { console.log('我会唱歌'); } } Star.sex = '男'; var ldh = new Star('刘德华', 18); console.log(ldh.sex); // Undefined console.log(Star.sex);//静态成员只能通过构造函数实例化对象来访问1.3构造函数的问题构造函数方法很好用，但是存在浪费内存的问题。console.log(ldh.sing === zxy.sing); //返回 false1.4构造函数原型prototype构造函数通过原型分配的函数是所有对象所共享的。JavaScript 规定，每一个构造函数都有一个prototype属性，指向另一个对象。注意这个prototype就是一个对象，这个对象的所有属性和方法，都会被构造函数所拥有。我们可以把那些不变的方法，直接定义在 prototype 对象上，这样所有对象的实例就可以共享这些方法。function Star(uname, age) { this.uname = uname; this.age = age; } Star.prototype.sing = function() { // 一般情况下，我们的公共属性定义到构造函数里面，公共的方法我们放到原型对象身上 console.log('我会唱歌'); } var ldh = new Star('刘德华', 18); var zxy = new Star('张学友', 19); ldh.sing();//我会唱歌 zxy.sing();//我会唱歌 console.log(ldh.sing === zxy.sing); //返回 true1.5对象原型对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象，之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法，就是因为对象有 __proto__ 原型的存在。__proto__对象原型和原型对象 prototype 是等价的，__proto__对象原型的意义就在于为对象的查找机制提供一个方向，或者说一条路线，但是它是一个非标准属性，因此实际开发中，不可以使用这个属性，它只是内部指向原型对象 prototype。function Star(uname, age) { this.uname = uname; this.age = age; } Star.prototype.sing = function() { console.log('我会唱歌'); } var ldh = new Star('刘德华', 18); var zxy = new Star('张学友', 19); ldh.sing(); console.log(ldh); // 对象身上系统自己添加一个 __proto__ 指向我们构造函数的原型对象 prototype console.log(ldh.__proto__ === Star.prototype); // 方法的查找规则: 首先先看ldh 对象身上是否有 sing 方法,如果有就执行这个对象上的sing // 如果么有sing 这个方法,因…