【前端开发之JavaScript】(四)JS基础语法下篇:函数与对象核心要点深度解析


目录

前言

[一、函数:JS 的 "代码积木"](#一、函数:JS 的 “代码积木”)

[1.1 函数的基本定义与调用](#1.1 函数的基本定义与调用)

[1.2 函数的参数特性:灵活的 "传参规则"](#1.2 函数的参数特性:灵活的 “传参规则”)

[1.3 函数表达式:把函数 "存进变量里"](#1.3 函数表达式:把函数 “存进变量里”)

[1.4 作用域与作用域链:函数的 "变量访问规则"](#1.4 作用域与作用域链:函数的 “变量访问规则”)

[1.4.1 全局作用域与局部作用域(函数作用域)](#1.4.1 全局作用域与局部作用域(函数作用域))

[1.4.2 作用域链:变量的 "链式查找规则"](#1.4.2 作用域链:变量的 “链式查找规则”)

[二、对象:JS 的 "万物皆对象"](#二、对象:JS 的 “万物皆对象”)

[2.1 对象的三种创建方式](#2.1 对象的三种创建方式)

[2.1.1 字面量方式创建对象【推荐】](#2.1.1 字面量方式创建对象【推荐】)

[2.1.2 使用 new Object 创建对象](#2.1.2 使用 new Object 创建对象)

[2.1.3 构造函数创建对象:批量创建 "同款对象"](#2.1.3 构造函数创建对象:批量创建 “同款对象”)

(1)构造函数的基本语法

[(2) 用 new 关键字创建对象](#(2) 用 new 关键字创建对象)

[(3) new 关键字的执行过程](#(3) new 关键字的执行过程)

[2.2 this 关键字:对象的 "身份标识"](#2.2 this 关键字:对象的 “身份标识”)

[2.3 JS 对象与 Java 对象的核心区别](#2.3 JS 对象与 Java 对象的核心区别)

[2.3.1 JS 没有 "类" 的概念(ES6 之前)](#2.3.1 JS 没有 “类” 的概念(ES6 之前))

[2.3.2 JS 对象不区分 "属性" 和 "方法"](#2.3.2 JS 对象不区分 “属性” 和 “方法”)

[2.3.3 JS 对象没有访问控制机制](#2.3.3 JS 对象没有访问控制机制)

[2.3.4 JS 通过原型实现 "继承",而非类继承](#2.3.4 JS 通过原型实现 “继承”,而非类继承)

[2.3.5 JS 没有 "多态" 的语法支持](#2.3.5 JS 没有 “多态” 的语法支持)

[三、函数与对象的结合:JS 编程的核心思维](#三、函数与对象的结合:JS 编程的核心思维)

总结


前言

在上一篇 JavaScript 语法基础中,我们聊到了 JS 的基本数据类型、运算符、流程控制和数组,这些内容是 JS 入门的基石。而函数和对象作为 JS 的核心组成部分,是实现代码复用、模块化开发以及模拟面向对象编程的关键,更是我们从 "入门" 走向 "进阶" 的必经之路。本文将结合实际代码案例,深入浅出地讲解 JS 中函数和对象的定义、使用、特性以及核心细节,让你彻底吃透这两大核心知识点!下面就让我们正式开始吧!


一、函数:JS 的 "代码积木"

在编程中,我们经常会遇到需要重复执行的代码逻辑,比如计算两个数的和、判断一个数是否为质数、渲染页面的某个模块。如果每次都重复写一遍相同的代码,不仅会让代码变得臃肿不堪,还会大大降低开发效率和可维护性。函数就是为了解决这个问题而生的 ------ 它是一段被封装起来的、可以重复调用的代码块,就像搭积木的零件,能被反复组合使用。

1.1 函数的基本定义与调用

JS 中定义函数的最基本方式是函数声明,语法格式清晰易懂,就像给一段代码起个名字,再规定它的输入和输出:

javascript 复制代码
// 函数声明:function 函数名(形参列表) { 函数体; return 返回值; }
function sum(num1, num2) {
    var result = num1 + num2;
    return result; // 返回计算结果
}
  • function:JS 中定义函数的关键字,必须写在最前面;
  • 函数名:遵循标识符命名规则,尽量做到 "见名知意",比如求和用sum、求阶乘用factorial
  • 形参列表:相当于函数的 "输入",可以理解为函数内部的临时变量,调用函数时才会被赋值;
  • 函数体:需要重复执行的代码逻辑,是函数的核心;
  • return:指定函数的 "输出",执行到return时函数会立即结束,后面的代码不会执行;如果没有return,函数默认返回undefined

定义函数后,必须调用才会执行 ,调用的方式也很简单:函数名(实参列表),实参就是给形参传递的具体值:

javascript 复制代码
// 调用函数,实参10和20会赋值给形参num1和num2
var total = sum(10, 20);
console.log(total); // 输出:30

// 不接收返回值也可以调用
sum(5, 8);

这里有一个非常重要的点:函数的定义和调用顺序没有要求,哪怕先调用再定义,代码也能正常执行,这一点和变量完全不同(变量必须先定义再使用):

javascript 复制代码
// 先调用函数,后定义函数,正常执行
hello();
function hello() {
    console.log("Hello JavaScript!");
}

1.2 函数的参数特性:灵活的 "传参规则"

JS 的函数传参非常灵活,实参和形参的个数可以不匹配,这是 JS 作为动态类型语言的典型特征,不过在实际开发中,我们还是建议让实参和形参个数保持一致,避免出现不必要的问题。具体的匹配规则分为两种:

(1)实参个数多于形参:多出的实参不会参与函数内部的运算,函数只会取前 N 个实参(N 为形参个数);

javascript 复制代码
function sum(num1, num2) {
    return num1 + num2;
}
// 实参有3个,形参只有2个,第三个实参30被忽略
var total = sum(10, 20, 30);
console.log(total); // 输出:30

(2)实参个数少于形参 :未被赋值的形参值为**undefined,此时如果进行运算,很可能得到NaN**;

javascript 复制代码
function sum(num1, num2) {
    return num1 + num2;
}
// 只传1个实参,num2为undefined
var total = sum(10);
console.log(total); // 输出:NaN

如果我们需要让函数支持任意个数的参数 ,可以使用 JS 内置的**arguments对象 ------ 它是函数内部的一个伪数组,包含了调用函数时传递的所有实参,能通过下标访问,也能通过length**获取参数个数:

javascript 复制代码
// 计算任意个数数字的和
function add() {
    var sum = 0;
    // 遍历arguments,累加所有实参
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}
console.log(add(10, 20)); // 输出:30
console.log(add(1, 2, 3, 4)); // 输出:10
console.log(add(5, 8, 10, 15, 20)); // 输出:58

1.3 函数表达式:把函数 "存进变量里"

除了函数声明,JS 中还有另一种定义函数的方式 ------函数表达式,它的核心是将一个匿名函数赋值给一个变量,通过变量来调用函数:

javascript 复制代码
// 函数表达式:匿名函数赋值给变量add
var add = function() {
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
};

// 通过变量调用函数
console.log(add(10, 20)); // 输出:30
console.log(typeof add); // 输出:function,说明变量的类型是函数

这里的function() {}匿名函数 ,没有函数名,只能通过赋值的变量来使用。需要注意的是,函数表达式的定义必须在调用之前,否则会报错,这一点和函数声明正好相反:

javascript 复制代码
// 先调用后定义,报错:add is not a function
add(10, 20);
var add = function() {
    return num1 + num2;
};

函数表达式的出现,印证了 JS 中一个重要的概念:函数是一等公民。也就是说,函数可以像普通变量一样被赋值、传递,也可以作为其他函数的参数或返回值,这为后续的高阶函数、闭包等知识点打下了基础。

1.4 作用域与作用域链:函数的 "变量访问规则"

写函数时,我们经常会遇到一个问题:不同位置的变量,哪些能访问,哪些不能访问?这就涉及到作用域------ 某个标识符(变量 / 函数名)在代码中的有效范围。在 ES6 之前,JS 的作用域主要分为两种:

1.4.1 全局作用域与局部作用域(函数作用域)

  • 全局作用域 :在整个**script标签中或单独的 JS 文件中生效,全局作用域中定义的变量称为全局变量**,任何地方都能访问;
  • 局部作用域(函数作用域) :在函数内部生效,函数内部定义的变量称为局部变量,只有函数内部能访问,外部无法访问。
javascript 复制代码
// 全局变量:在script标签中定义,任何地方都能访问
var num = 10;
console.log(num); // 输出:10

function test1() {
    // 局部变量:只有test1内部能访问
    var num = 20;
    console.log(num); // 输出:20
}

function test2() {
    // 局部变量:只有test2内部能访问
    var num = 30;
    console.log(num); // 输出:30
}

test1();
test2();
// 外部依然访问全局变量num
console.log(num); // 输出:10

这里有一个坑需要注意:创建变量时如果不写var关键字,会默认创建全局变量,哪怕是在函数内部:

javascript 复制代码
function test() {
    // 没有写var,num成为全局变量
    num = 100;
}
test();
// 外部能访问到函数内部定义的num
console.log(num); // 输出:100

另外,和 Java、C++ 等语言不同,JS 在 ES6 之前,局部作用域不是按大括号{}划分的,if、for 等语句的大括号中定义的变量,依然是全局变量:

javascript 复制代码
if (1 < 2) {
    // 大括号中定义的变量a,是全局变量
    var a = 10;
}
// 外部能正常访问a
console.log(a); // 输出:10

1.4.2 作用域链:变量的 "链式查找规则"

JS 中函数可以嵌套定义,也就是在一个函数内部定义另一个函数。此时,内层函数可以访问外层函数的局部变量 ,这种访问规则遵循作用域链 :变量的查找会从当前作用域开始,从内到外依次查找 ,找到则使用,找不到则继续向上,直到全局作用域;如果全局作用域也没有,就会报错**xxx is not defined**。

javascript 复制代码
// 全局作用域的num
var num = 1;
function test1() {
    // test1作用域的num
    var num = 10;
    function test2() {
        // test2作用域的num
        var num = 20;
        console.log(num); // 先找test2内部,找到num=20,输出:20
    }
    test2();
}
test1();

如果我们删除 test2 内部的 num,变量查找会向上到 test1 作用域;如果再删除 test1 内部的 num,就会找到全局作用域的 num:

javascript 复制代码
var num = 1;
function test1() {
    var num = 10;
    function test2() {
        // 没有自己的num,向上找test1的num=10
        console.log(num); // 输出:10
    }
    test2();
}
test1();

作用域链的本质是:内部函数会保存外部函数的作用域,形成一个链式的作用域结构,这也是闭包的核心原理。

二、对象:JS 的 "万物皆对象"

在现实生活中,我们接触的每一个事物都是一个对象,比如一台电脑、一只猫咪、一个学生:电脑有品牌、型号、配置等特征 ,也有开机、关机、运行程序等行为;猫咪有名字、品种、颜色等特征,也有叫、跑、跳等行为。

在 JS 中,对象就是对现实事物的抽象,它是一个无序的键值对集合,其中:

  • 键(key) :表示事物的特征或行为,特征称为属性 ,行为称为方法
  • 值(value) :属性的值可以是任意基本数据类型(数字、字符串、布尔等),方法的值是函数

JS 中有一句经典的话:万物皆对象。字符串、数值、数组、函数都是对象,甚至连浏览器窗口、文档节点都是对象。对象的出现,让我们可以更清晰、更结构化地存储和操作数据,相比数组(只能通过下标访问),对象通过属性名访问数据,语义更明确,可读性更高。

比如表示一个学生的信息,用数组的话是这样的:

javascript 复制代码
// 数组:下标0是姓名,1是身高,2是体重,语义不明确
var student = ['蔡徐坤', 175, 170];

别人看到这段代码,根本不知道 175 和 170 分别代表什么;而用对象的话,语义一目了然:

javascript 复制代码
// 对象:属性名name、height、weight明确表示含义
var student = {
    name: '蔡徐坤',
    height: 175,
    weight: 170
};

2.1 对象的三种创建方式

JS 中创建对象的方式有三种,其中字面量方式是最常用、最简洁的,构造函数方式适合创建多个具有相同结构的对象,我们逐一讲解。

2.1.1 字面量方式创建对象【推荐】

使用**大括号{}创建对象,是 JS 中最常用的方式,直接在{}中定义属性和方法,键值对 的形式组织,键和值之间用:分隔,键值对之间用,**分隔,最后一个键值对的,可以省略。

javascript 复制代码
// 创建空对象
var obj = {};

// 创建包含属性和方法的对象
var student = {
    // 属性:键是name,值是'蔡徐坤'
    name: '蔡徐坤',
    height: 175,
    weight: 170,
    // 方法:键是sayHello,值是匿名函数
    sayHello: function() {
        console.log("Hello, 我是" + this.name);
    }
};

这里的**this是 JS 中的关键字,在对象的方法中,this指向当前对象**,也就是调用这个方法的对象,后面会详细讲解。

访问对象的属性和方法有两种方式:

  1. 点访问符(.) :最常用,语法为对象名.属性名/对象名.方法名().可以理解为 "的";
  2. 方括号访问符([]) :语法为对象名['属性名']/对象名'方法名',属性名必须用引号引起来,适合属性名包含特殊字符的场景。
javascript 复制代码
// 访问属性
console.log(student.name); // 点访问,输出:蔡徐坤
console.log(student['height']); // 方括号访问,输出:175

// 调用方法,别忘记加()
student.sayHello(); // 点调用,输出:Hello, 我是蔡徐坤
student['sayHello'](); // 方括号调用,输出:Hello, 我是蔡徐坤

对象的属性和方法可以随时新增和修改,这也是 JS 对象的灵活之处:

javascript 复制代码
// 新增属性
student.age = 25;
student['gender'] = '男';

// 修改属性
student.height = 178;

// 新增方法
student.study = function() {
    console.log(this.name + '正在学习JavaScript');
};

// 调用新方法
student.study(); // 输出:蔡徐坤正在学习JavaScript
console.log(student); // 输出包含所有属性和方法的对象

2.1.2 使用 new Object 创建对象

**new Object()**是 JS 中创建对象的原生方式,相当于字面量方式的 "官方写法",先创建空对象,再通过点访问符或方括号访问符添加属性和方法:

javascript 复制代码
// 创建空对象
var student = new Object();

// 新增属性
student.name = "蔡徐坤";
student.height = 175;
student['weight'] = 170;

// 新增方法
student.sayHello = function () {
    console.log("Hello, 我是" + this.name);
};

// 访问属性和调用方法
console.log(student.name); // 输出:蔡徐坤
student.sayHello(); // 输出:Hello, 我是蔡徐坤

这种方式和字面量方式创建的对象本质上是一样的,只是写法不同,实际开发中更推荐字面量方式,因为更简洁。

2.1.3 构造函数创建对象:批量创建 "同款对象"

如果我们需要创建多个具有相同结构的对象,比如多只猫咪、多个学生、多个商品,用字面量或**new Object**的方式会重复写大量相同的代码,非常麻烦。此时,构造函数就是最佳选择 ------ 它是一个特殊的函数,专门用于创建对象,能把对象的公共属性和方法提取出来,实现批量创建。

(1)构造函数的基本语法

构造函数的定义和普通函数类似,但有几个特殊的规范和要求:

  1. 构造函数的函数名首字母必须大写,用于区分普通函数;
  2. 函数内部使用this 关键字 表示当前正在构建的对象,给 this 添加属性和方法,就是给创建的对象添加属性和方法;
  3. 构造函数不需要 return,会自动返回创建的对象;
  4. 创建对象时必须使用 new 关键字,不能直接调用。
javascript 复制代码
// 构造函数:首字母大写,参数为对象的公共属性
function Cat(name, type, sound) {
    // this指向即将创建的猫咪对象
    this.name = name;
    this.type = type;
    // 给对象添加方法
    this.miao = function () {
        console.log(sound);
    }
}
(2) 用 new 关键字创建对象

使用**new 构造函数名(实参)**就能批量创建对象,每个对象都有独立的属性和方法,互不影响:

javascript 复制代码
// 创建3只猫咪对象,传递不同的实参
var mimi = new Cat('咪咪', '中华田园喵', '喵');
var xiaohei = new Cat('小黑', '波斯喵', '猫呜');
var ciqiu = new Cat('刺球', '金渐层', '咕噜噜');

// 访问对象的属性
console.log(mimi.name); // 输出:咪咪
console.log(xiaohei.type); // 输出:波斯喵

// 调用对象的方法
mimi.miao(); // 输出:喵
ciqiu.miao(); // 输出:咕噜噜
(3) new 关键字的执行过程

很多同学会好奇,为什么只要写new 构造函数就能创建对象?其实new关键字背后做了 4 件事,这是 JS 的核心面试考点,一定要掌握:

  1. 在内存中创建一个空的对象
  2. 将 this 指向这个空对象,让构造函数的 this 绑定到新对象上;
  3. 执行构造函数的代码,给空对象添加属性和方法;
  4. 自动返回这个新对象(构造函数不需要写 return,new 会代劳)。

理解了 new 的执行过程,就能明白为什么构造函数必须用 new 调用:如果不用 new,构造函数就是普通函数,this 会指向全局对象(浏览器中是 window),而不是新创建的对象,会造成全局变量污染。

2.2 this 关键字:对象的 "身份标识"

在 JS 中,this是一个非常重要且灵活的关键字,它的核心是指向调用者 ,简单来说:谁调用,this 就指向谁 。在不同的场景下,this的指向不同,我们这里重点讲解对象方法中的 this,这是最常用的场景。

在对象的方法中,this 指向调用这个方法的对象 ,也就是当前对象。这样一来,不同的对象调用同一个方法,this会指向不同的对象,从而实现方法的复用。

javascript 复制代码
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.sayHi = function() {
        // this指向调用sayHi的Person对象
        console.log("我是" + this.name + ", 今年" + this.age + "岁");
    }
}

var p1 = new Person('张三', 20);
var p2 = new Person('李四', 25);

// p1调用sayHi,this指向p1
p1.sayHi(); // 输出:我是张三, 今年20岁
// p2调用sayHi,this指向p2
p2.sayHi(); // 输出:我是李四, 今年25岁

如果直接单独调用方法,而不是通过对象调用,this 会指向全局对象 window(浏览器中),此时属性会变成 window 的属性,这是我们需要避免的:

javascript 复制代码
// 直接调用方法,this指向window
var sayHi = p1.sayHi;
sayHi(); // 输出:我是undefined, 今年undefined岁

2.3 JS 对象与 Java 对象的核心区别

很多同学都是先学 Java 再学 JS,很容易把两个语言的对象概念混淆。虽然 JS 和 Java 都有 "对象" 的概念,也都有属性和方法,但二者的差异非常大,核心区别有 5 点,掌握这些区别能让你更深刻地理解 JS 的对象模型:

2.3.1 JS 没有 "类" 的概念(ES6 之前)

Java 是纯粹的面向对象语言,一切皆类,对象是类的实例,必须先定义类,再通过类创建对象;而 JS 在 ES6 之前没有类的概念 ,对象是直接通过字面量、new Object或构造函数创建的,构造函数只是起到了类似 "类" 的作用,用于批量创建对象。

ES6 中引入了**class关键字,让 JS 可以像 Java 一样定义类和创建对象,但这只是语法糖**,底层依然是基于构造函数和原型实现的,并不是真正的类。

2.3.2 JS 对象不区分 "属性" 和 "方法"

在 Java 中,属性是成员变量,方法是成员函数,二者是严格区分的;而在 JS 中,函数是一等公民 ,方法本质上是 "值为函数的属性",和普通属性没有本质区别,只是这个属性的值可以通过**()**调用。

javascript 复制代码
var obj = {
    // 普通属性:值是字符串
    name: 'JS',
    // 方法:值是函数,本质也是属性
    sayHello: function() {
        console.log("Hello");
    }
};
// 可以像修改普通属性一样修改方法
obj.sayHello = function() {
    console.log("Hello JavaScript");
};
obj.sayHello(); // 输出:Hello JavaScript

2.3.3 JS 对象没有访问控制机制

Java 中有privatepublicprotected等访问修饰符,用于控制属性和方法的访问权限,比如private的属性只能在类内部访问;而 JS 中没有任何访问控制机制,对象的所有属性和方法都能被外界随意访问、修改和删除,没有 "私有属性 / 方法" 的概念(ES6 中可以通过 Symbol 实现私有属性,属于进阶内容)。

2.3.4 JS 通过原型实现 "继承",而非类继承

Java 的继承是类的继承 ,子类继承父类,能继承父类的属性和方法;而 JS 中没有类的继承 ,而是通过原型(prototype) 机制实现类似的继承效果,核心是让一个对象的__proto__属性指向另一个对象,从而实现属性和方法的复用。

当访问一个对象的属性或方法时,如果对象自身没有,会去它的原型对象中查找;如果原型对象也没有,会去原型的原型中查找,直到找到 Object 的原型(Object.prototype),如果还没找到,就返回undefined,这个过程称为原型链

javascript 复制代码
// 原型对象:包含公共的方法eat
var animal = {
    eat: function() {
        console.log(this.name + "正在吃饭");
    }
};

// 猫对象:__proto__指向animal,继承eat方法
var cat = {
    name: '咪咪',
    __proto__: animal
};

// 狗对象:__proto__指向animal,继承eat方法
var dog = {
    name: '旺财',
    __proto__: animal
};

// 猫和狗都能调用原型对象的eat方法
cat.eat(); // 输出:咪咪正在吃饭
dog.eat(); // 输出:旺财正在吃饭

原型和原型链是 JS 的核心难点,也是面试的高频考点,后续会专门写一篇文章详细讲解。

2.3.5 JS 没有 "多态" 的语法支持

Java 的多态是基于类的继承和方法重写 实现的,比如父类引用指向子类对象,调用方法时会执行子类的重写方法;而 JS 作为动态类型语言,本身就支持 "多态" 的特性 ------ 调用对象的方法时,不需要关注对象的类型,只要对象有这个方法就能调用,因此不需要在语法层面专门支持多态。

javascript 复制代码
// 定义一个add函数,只要参数list有add方法就能调用
function add(list, s) {
    list.add(s);
}

// 自定义一个数组对象,有add方法
var arr1 = {
    data: [],
    add: function(s) {
        this.data.push(s);
        console.log("添加成功:" + s);
    }
};

// 原生数组,本身有push方法,我们给它添加add方法
var arr2 = [1,2,3];
arr2.add = function(s) {
    this.push(s);
    console.log("数组添加:" + s);
};

// 调用add函数,传入不同的对象,只要有add方法就能执行
add(arr1, 'JS'); // 输出:添加成功:JS
add(arr2, 4); // 输出:数组添加:4

从上面的代码可以看出,JS 的多态是 "天生的",不需要像 Java 那样通过类继承来实现,这也是 JS 作为动态语言的灵活性体现。

三、函数与对象的结合:JS 编程的核心思维

函数和对象并不是孤立的,而是紧密结合的,二者的结合形成了 JS 编程的核心思维 ------将函数作为对象的方法,实现代码的结构化和复用

在实际开发中,我们不会单独写一堆函数,而是会将相关的函数封装到一个对象中,作为对象的方法,这样不仅能让代码的语义更明确,还能避免全局变量污染。比如实现一个 "计算器" 功能,我们可以把加法、减法、乘法、除法封装到一个计算器对象中:

javascript 复制代码
// 计算器对象:包含计算相关的方法
var calculator = {
    add: function(num1, num2) {
        return num1 + num2;
    },
    sub: function(num1, num2) {
        return num1 - num2;
    },
    mul: function(num1, num2) {
        return num1 * num2;
    },
    div: function(num1, num2) {
        if (num2 === 0) {
            console.log("除数不能为0");
            return undefined;
        }
        return num1 / num2;
    }
};

// 调用计算器对象的方法
console.log(calculator.add(10, 20)); // 输出:30
console.log(calculator.mul(5, 8)); // 输出:40
console.log(calculator.div(20, 0)); // 输出:除数不能为0,返回undefined

这种方式就是模块化编程的雏形,将相关的功能封装到一个对象中,形成一个独立的模块,后续可以直接复用这个模块,也方便维护和扩展。


总结

函数和对象是 JS 的核心,也是后续学习 DOM/BOM、AJAX、Vue/React 等框架的基础,一定要多敲代码、多练习,把基础打牢。比如尝试用构造函数创建一个 "学生管理系统",包含添加学生、删除学生、查询学生等方法;或者用对象封装一个 "时钟" 模块,包含获取当前时间、格式化时间等方法。只有通过实践,才能真正理解和掌握这些知识点。

创作不易,如果这篇文章对你有帮助,欢迎点赞、收藏、关注一波~

相关推荐
键盘鼓手苏苏1 小时前
Flutter for OpenHarmony:dart_ping 网络诊断的瑞士军刀(支持 ICMP Ping) 深度解析与鸿蒙适配指南
开发语言·网络·flutter·华为·rust·harmonyos
CodeByV1 小时前
【Qt】窗口
开发语言·qt
白露与泡影1 小时前
Java 春招高级面试指南( Java 面试者必备)
java·开发语言·面试
大尚来也2 小时前
Python 调用 Ollama 本地大模型 API 完全指南
开发语言·python
henry1010102 小时前
通过GitHub Page服务免费部署静态Web网站
前端·html·github·html5
少云清2 小时前
【UI自动化测试】3_web自动化测试 _Selenium-IDE
前端·selenium·web自动化测试
qq_24218863322 小时前
Python 春节贺卡代码
开发语言·python
强子感冒了2 小时前
JavaScript学习笔记:函数、方法与继承(原型与class)
javascript·笔记·学习
wuqingshun3141592 小时前
说一下java的四种引用
java·开发语言