JavaScript笔记

21 阅读7分钟

JavaScript文件运行

使用node.js运行JavaScript文件,不使用浏览器。
1. 运行单文件 文件名:helloworld.js

const say="hello world!!!";
console.log(say);

运行指令:

node helloworld.js

# 输出
hello world!!!
  1. 运行多文件 建立package.json文件,否则失败
{
  "name": "js模块化",
  "version": "1.0.0",
  "type": "module",
  "main": "main.js"
}
// main.js
import { PI, sayHello, Person } from './module.js';
import myFunction from './module.js';
// import {a} from './moudel2.js';
sayHello();
const person = new Person('John');
person.greet();
myFunction();
// module.js
export const PI = 3.14;

export function sayHello() {
    console.log('Hello, World!');
}

export class Person {
    constructor(name) {
        this.name = name;
    }

    greet() {
        console.log(`Hello, my name is ${this.name}`);
    }
}

export default function sayGoodbye() {
    console.log('Goodbye, World!');
}

运行指令

node main.js

# 运行结果:
Hello, World!
Hello, my name is John
Goodbye, World!

关键字

export

export default{ message }export default message 的区别:在 JavaScript 中,export default 用于导出模块的默认导出项。它可以导出任何有效的 JavaScript 表达式,如函数、对象、原始类型等。下面是两种不同的 export default 用法及其区别:

  1. 导出的形式:

    1. 使用大括号:这种形式实际上是导出一个对象,并将对象的所有属性和方法作为模块的默认导出。在导入时,需要使用对象解构语法来访问对象中的属性或方法。
    2. 直接导出:这种形式直接导出一个值(可以是字符串、数字、布尔值、函数、对象等)。在导入时,不需要使用解构语法,可以直接使用导入的名字来访问。
  2. 导入的方式

    1. 使用大括号:导入时需要使用解构语法来访问对象中的属性。 示例:
    import { message } from './module.js';
    console.log(message); // 输出 "Hello, World!"
    
    1. 直接导出:导入时可以使用任意名字,不需要使用解构语法。示例:
import greeting from './module.js';
console.log(greeting); // 输出 "Hello, World!"
// module1.js
export default {
  message: "Hello, World!"
};
// module2.js
export default "Hello, World!";
// app.js
import { message } from './module1.js';
import greeting from './module2.js';

console.log(message); // 输出 "Hello, World!"
console.log(greeting); // 输出 "Hello, World!"

总结

  • 使用大括号 {} 的形式适用于导出包含多个属性或方法的对象。
  • 直接导出的形式适用于导出单一的值或对象。
  • 导入时,使用大括号的形式需要解构语法来访问对象中的属性,而直接导出的形式则可以直接使用导入的名字来访问。

debugger

debugger用于停止执行 JavaScript,并调用调试函数。这个关键字与在调试工具中设置断点的效果是一样的。如果没有调试可用,debugger 语句将无法工作。开启 debugger ,代码在第三行前停止执行。

var x = 15 * 5;
debugger;
document.getElementbyId("demo").innerHTML = x;

函数

函数表达式

JavaScript 函数可以通过一个表达式定义。函数表达式可以存储在变量中:

var x = function (a, b) {return a * b};

在函数表达式存储在变量后,变量也可作为一个函数使用:

var x = function (a, b) {return a * b};
var z = x(4, 3);

以上函数实际上是一个 匿名函数 (函数没有名称)。函数存储在变量中,不需要函数名称,通常通过变量名来调用。

javascript调用python代码

只调用一次

只调用一次,返回数据也一次

# server.py
import sys
import cv2
import numpy as np

def sendImage(file_path):
    # 读取图像
    img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)

    # 传递数据到Node.js端,使用字节流的形式
    _,img_encoded = cv2.imencode('.png',img)

    sys.stdout.buffer.write(img_encoded.tobytes())

# 从命令行参数中获取数据
#file_path:str = sys.argv[1]
#sendImage(file_path)

def sendText(text:str):
    buffer = text.encode('utf-8')
    sys.stdout.buffer.write(buffer)
    
# 从命令行参数中获取数据
#text:str = sys.argv[1]
#sendText(text)
// client.js
import { spawn } from "node:child_process";
import fs from "node:fs";

export async function callPythonScript(scriptPath, args) {
  return new Promise((resolve, reject) => {
    const pythonProcess = spawn("python", [scriptPath, ...args]);
    let buffData = Buffer.from([]);
    pythonProcess.stdout.on("data", (data) => {
      // 将接收到的数据追加到 Buffer 中
      buffData = Buffer.concat([buffData, data]);
    });

    pythonProcess.stderr.on("data", (data) => {
      reject(data.toString());
    });

    pythonProcess.on("close", (code) => {
      console.log(`Python script process exited with code ${code}`);
      resolve(buffData);
    });
  });
}

const args = ["./悬崖.png"];
await callPythonScript("./server.py", args).then((data) => {
    fs.writeFileSync('./fs/result.png',data)
});

不停发送消息

调用过程不停发送消息,消息间是需要分割的

# server.py
import sys
import cv2
import numpy as np
import time

def sendText():
    for i in range(10):
        text = 'hello world ' + str(i)
        buffer = text.encode('utf-8')
        sys.stdout.buffer.write(buffer)
        sys.stdout.flush()
        time.sleep(1)

# 从命令行参数中获取数据
#arg:str = sys.argv[1]
#sendText()
//cliet.js
import { spawn } from "node:child_process";
import fs from "node:fs";
import path from "node:path";

// 自定义回调函数:处理接收到的数据
function getText(data) {
  console.log('Data received:', data.toString()+' 233'); // 去掉换行符并输出
  // 这里可以添加其他逻辑,例如将数据传递到其他模块或触发事件
}

export async function callPythonScript(scriptPath, args,handleData) {
  return new Promise((resolve, reject) => {
    const pythonProcess = spawn("python", [scriptPath, ...args]);
   
    pythonProcess.stdout.on("data", (data) => {
      handleData(data)
    });

    pythonProcess.stderr.on("data", (data) => {
      reject(data.toString());
    });

    pythonProcess.on("close", (code) => {
      resolve(code);
    });
  });
}

const args = ["./悬崖.png"];
callPythonScript("./server.py", args,getText).then((data) => {
    console.log('0')
});

websocket

安装:

  1. node.js需要安装ws库
npm install ws
  1. python需要安装websockets库
pip install websockets

只发送数据

简单实现,后端只发送数据,不接受数据,前端只接受数据,不发送,

# 服务端 server.py
import asyncio
import websockets
from datetime import datetime

async def time_sender(websocket):
    try:
        while True:
            # 获取当前时间戳
            current_time = str(datetime.now().timestamp())

            # 发送时间戳到客户端
            await websocket.send(current_time)

            # 每隔一秒发送一次
            await asyncio.sleep(1)
    except websockets.ConnectionClosed:
        print("Connection with client closed")


async def main():
    # 设置服务器启动参数
    async with websockets.serve(time_sender, "localhost", 8765):
        print("WebSocket server started at ws://localhost:8765")
        # 运行服务器直到程序被停止
        await asyncio.Future()  # Run forever

if __name__ == "__main__":
    asyncio.run(main())
// 客户端 client.js
const WebSocket = require('ws');
// 创建WebSocket客户端实例
const ws = new WebSocket('ws://localhost:8765');
// 当连接打开时触发
ws.on('open', function open() {
    console.log('Connected to WebSocket server.');
});
// 当从服务器接收到消息时触发
ws.on('message', function incoming(message) {
    console.log('Received timestamp:', message.toString());
});
// 错误处理
ws.on('error', function error(err) {
    console.error('WebSocket error:', err);
});
// 连接关闭时触发
ws.on('close', function close() {
    console.log('Disconnected from WebSocket server.');
});

发送图片

# 服务端 server.py
import asyncio
import websockets
import base64
from datetime import datetime

async def send_image(websocket):
    try:
        # 读取图片文件并转换为base64编码的字符串
        with open("./悬崖.png", "rb") as image_file:
            encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
        
        # 发送图片到客户端
        await websocket.send(encoded_string)
        
        while True:
            await asyncio.sleep(1)  # 持续保持连接
    except websockets.ConnectionClosed:
        print("Connection with client closed")

async def main():
    async with websockets.serve(send_image, "localhost", 8765):
        print("WebSocket server started at ws://localhost:8765")
        await asyncio.Future()  # Run forever

if __name__ == "__main__":
    asyncio.run(main())
<!-- 客户端:client.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>WebSocket Image Display</title>
    </head>
    <body>
        <h2>Received Image from WebSocket Server</h2>
        <img id="receivedImage" alt="Received Image" style="width:300px;height:auto;"/>
        <script>
            const socket = new WebSocket('ws://localhost:8765');

            socket.onmessage = function(event) {
                // 设置img元素的src属性为接收到的base64字符串
                document.getElementById('receivedImage').src = 'data:image/png;base64,' + event.data;
            };

            socket.onopen = function(event) {
                console.log('Connected to WebSocket server.');
            };

            socket.onerror = function(error) {
                console.error('WebSocket error observed:', error);
            };

            socket.onclose = function(event) {
                console.log('Disconnected from WebSocket server.');
            };
        </script>
    </body>
</html>

发送视频

# 服务端 server.py
import asyncio
import websockets
import cv2
import base64
import numpy as np

async def send_video(websocket):
    try:
        # 打开视频文件
        cap = cv2.VideoCapture(0)

        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break

            # 将帧转换为JPEG格式以减少数据量
            _, img_encoded = cv2.imencode(".jpg", frame)
            encoded_string = base64.b64encode(img_encoded).decode("utf-8")

            # 发送编码后的图像到客户端
            await websocket.send(f"data:image/jpeg;base64,{encoded_string}")

            # 控制发送速率,避免过快导致网络拥塞
            await asyncio.sleep(0.03)  # 约30帧每秒

        cap.release()
        print("Video stream ended.")

    except websockets.ConnectionClosed:
        print("Connection with client closed")


async def main():
    async with websockets.serve(send_video, "localhost", 8765):
        print("WebSocket server started at ws://localhost:8765")
        await asyncio.Future()  # Run forever

if __name__ == "__main__":
    asyncio.run(main())

<!--客户端 client.html-->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>WebSocket Video Stream</title>
        <style>
            #videoStream {
                width: 640px;
                height: 480px;
            }
        </style>
    </head>
    <body>
        <h2>Received Video Stream from WebSocket Server</h2>
        <img id="videoStream" alt="Video Stream" />

        <script>
            const socket = new WebSocket('ws://localhost:8765');

            let lastFrameTime = performance.now();

            socket.onmessage = function(event) {
                const now = performance.now();
                // 控制帧率,避免过快更新导致浏览器卡顿
                if (now - lastFrameTime >= 1000 / 30) { // 约30帧每秒
                    document.getElementById('videoStream').src = event.data;
                    lastFrameTime = now;
                }
            };

            socket.onopen = function(event) {
                console.log('Connected to WebSocket server.');
            };

            socket.onerror = function(error) {
                console.error('WebSocket error observed:', error);
            };

            socket.onclose = function(event) {
                console.log('Disconnected from WebSocket server.');
            };
        </script>
    </body>
</html>

发送数据且接受数据

后端发送数据和接受数据,前端接受数据和发送,二者可以分开

# 服务端  server.py
import asyncio
import websockets
import datetime


async def send_timestamps(websocket):
    """定时发送时间戳到客户端"""
    try:
        while True:
            # 发送当前时间戳到客户端
            timestamp = datetime.datetime.now().isoformat()
            await websocket.send(timestamp)
            # print(f"Sent timestamp to client: {timestamp}")

            # 等待1秒
            await asyncio.sleep(1)
    except websockets.ConnectionClosed:
        print("Client disconnected during sending")


async def receive_messages(websocket):
    """接收客户端发送的消息"""
    try:
        while True:
            # 接收客户端发送的消息
            message = await websocket.recv()
            print(f"Received message from client: {message}")
    except websockets.ConnectionClosed:
        print("Client disconnected during receiving")


async def handle_connection(websocket):
    """处理客户端连接"""
    print("Client connected")

    # 创建发送和接收任务
    send_task = asyncio.create_task(send_timestamps(websocket))
    receive_task = asyncio.create_task(receive_messages(websocket))

    # 等待任务完成(任意一个任务完成时退出)
    await asyncio.gather(send_task, receive_task)


async def main():
    # 启动 WebSocket 服务器
    async with websockets.serve(handle_connection, "localhost", 8765):
        print("WebSocket server started on ws://localhost:8765")
        await asyncio.Future()  # 永久运行


# 显式创建并运行事件循环
if __name__ == "__main__":
    asyncio.run(main())

// 客户端1 client.js
const WebSocket = require("ws");

// 连接到WebSocket服务器
const ws = new WebSocket("ws://localhost:8765");

ws.on("open", function open() {
    console.log("Connected to server");

    // 模拟客户端随时发送消息
    setTimeout(() => {
        const message = "Hello from client";
        ws.send(message);
        console.log(`Sent message to server: ${message}`);
    }, 3000); // 3秒后发送消息

    setTimeout(() => {
        const message = "Another message from client";
        ws.send(message);
        console.log(`Sent message to server: ${message}`);
    }, 6000); // 6秒后发送消息
});

// 接收服务器发送的消息
ws.on("message", function message(data) {
    console.log(`Received timestamp from server: ${data}`);
});

ws.on("close", function close() {
    console.log("Disconnected from server");
});

<!-- 客户端2 client.js -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>WebSocket Client</title>
    </head>
    <body>
        <h1>WebSocket Client</h1>
        <p>Click the buttons to send messages to the server:</p>
        <button id="button1">Send Message 1</button>
        <button id="button2">Send Message 2</button>

        <script>
            // 连接到 WebSocket 服务器
            const ws = new WebSocket("ws://localhost:8765");

            // 连接成功时触发
            ws.onopen = function () {
                console.log("Connected to WebSocket server");
            };

            // 接收到服务器消息时触发
            ws.onmessage = function (event) {
                console.log("Received from server:", event.data);
            };

            // 连接关闭时触发
            ws.onclose = function () {
                console.log("Disconnected from WebSocket server");
            };

            // 处理按钮点击事件
            document.getElementById("button1").addEventListener("click", function () {
                const message = "Button 1 clicked";
                ws.send(message);
                console.log("Sent to server:", message);
            });

            document.getElementById("button2").addEventListener("click", function () {
                const message = "Button 2 clicked";
                ws.send(message);
                console.log("Sent to server:", message);
            });
        </script>
    </body>
</html>

Ajax

AJAX = 异步 JavaScript 和 XML。是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
Ajax实例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>页面标题</title>
</head>
<body>
    <div id="myDiv">
        <h2>使用 AJAX 修改该文本内容</h2>
    </div>
    <button type="button" onclick="loadXMLDoc()">修改内容</button>
    <script>
        function loadXMLDoc() {
            var xmlhttp;
            if (window.XMLHttpRequest) {
                //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
                xmlhttp = new XMLHttpRequest();
            }
            else {
                // IE6, IE5 浏览器执行代码
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
                }
            }
            xmlhttp.open("GET", "/try/ajax/ajax_info.txt", true);
            xmlhttp.send();
        }
    </script>
</body>
</html>
  1. 第一步:建立对象:XMLHttpRequest 对象用于和服务器交换数据。
var xmlhttp = new XMLHttpRequest();
  1. 第二步:发送请求: 如需将请求发送到服务器,我们使用XMLHttpRequest对象的 open()send() 方法:
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
方法描述
open(method,url,async)规定请求的类型、URL 以及是否异步处理请求。
method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)
send(string)将请求发送到服务器。string:仅用于 POST 请求
  1. 第三步:Async=true,当使用 async=true 时,请规定在响应处于 onreadystatechange 事件中的就绪状态时执行的函数:
   xmlhttp.onreadystatechange=function() {    
   if (xmlhttp.readyState==4 && xmlhttp.status==200){        document.getElementById("myDiv").innerHTML=xmlhttp.responseText;    
   	} 
   } 
   xmlhttp.open("GET","/try/ajax/ajax_info.txt",true);
   xmlhttp.send();
  1. 第四步:获取响应,如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseTextresponseXML 属性。
属性描述
responseText获得字符串形式的响应数据。
responseXML获得 XML 形式的响应数据。
  1. 第五步:onreadystatechange 事件,当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。readyState 属性存有 XMLHttpRequest 的状态信息。下面是 XMLHttpRequest 对象的三个重要的属性:
属性描述
onreadystatechange存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。
readyState存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
status200: "OK"
404: 未找到页面

在 onreadystatechange 事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。当 readyState 等于 4 且状态为 200 时,表示响应已就绪。