0
点赞
收藏
分享

微信扫一扫

JavaScript基础知识

绪风 2022-02-23 阅读 68

初识 JavaScript

参照传智播客的视频。

定义

javascript是一种运行在客户端的脚本语言 (与css类似)

作用

  • 表单动态检验
  • 网页特效
  • 服务端开发(Node.js)
  • 桌面程序(Electron)
  • APP(Cordova)
  • 控制硬件-物联网(Ruff)
  • 游戏开发(cocos2d-js)

js的组成

1.javascript语法(ECMAScript)
2.面向文档对象模型(DOM)
3.浏览器对象模型(BOM)

JavaScript 变量

定义

程序在内存中申请的一块用来存放数据的## 空间

使用

1.声明变量 2. 赋值

// 声明用关键词var
var  age; // 声明一个名称为age的变量
// 赋值
age=10; // 给age这个变量赋值
// 变量的初始化
var age = 18; // 推荐写法

案例

变量的使用: 1.弹出一个对话框,提示用户输入姓名
2.弹出一个对话框,输出用户刚才输入姓名

	var myname = prompt('请输入您的姓名');
    alert(myname);

输出结果:
在这里插入图片描述

变量语法扩展

  1. 更新变量
var age = 18;
age = 20; // 第二次的值会把第一次的完全覆盖
  1. 声明多个变量
var age=18,address='火影村'; // 多个变量之间用逗号隔开
  1. 特殊情况
var sex; // 只声明不赋值 结果是undefined
console.log(tel); 不声明,不赋值,直接使用某个变量会报错的
qq = 110; // 不声明直接赋值使用 

变量的命名规则

在这里插入图片描述

案例

交换两个变量的值

	var temp; // 临时变量
    var apple1='青苹果';
    var apple2 = '红苹果';
    temp = apple1;
    apple1 = apple2;
    apple2 = temp;
    console.log(apple1);
    console.log(apple2);

小结

在这里插入图片描述

JavaScript数据类型

数据类型简介

// js的变量数据类型是只有程序在运行过程中,根据等号右边的值来确定的
var num = 10; // 数值型
var str = 'pink' // 字符串型
// js动态语言,变量的数据类型可以变化

简单数据类型

在这里插入图片描述

数字型 Number

var num = 10;
var PI = 3.14;
// 1.八进制 0-7 我们程序里面数字前面加0 表示八进制
var num1 = 010; // 010 八进制 转换为10进制 就是8
// 2.十六进制 0-9 a-f 在程序数字前加0x 表示十六进制
var num2= 0xa; // 10
// 3.数字型的最大值 (了解)
alert(Number.MAX_VALUE);
alert(Number.MIN_VALUE);
// 三个特殊词 (了解)
alert(Infinity) // 无穷大
alert(-Infinity) // 无穷小
alert(NaN) // 非数字

isNaN() 这个方法用来判断非数字
在这里插入图片描述

字符串型 String

可以是单引号或双引号 在js中推荐用单引号

嵌套

口诀: 外双内单,内双外单

var str = '我是一个"高富帅"的程序员';

字符串转义符

转义符解释说明
\ n换行符 newline
\ \斜杠 \
\ ’单引号’
\”双引号"
\ttab缩进
\b空格

字符串长度

获取字符串的长度可用length属性

var str = 'my name is andy';
console.log(str.length) // 15

字符串拼接 +

拼接方式:字符串+任何类型 = 拼接之后的字符串
+号口诀:数值相加,字符相连
拼接加强: 将字符串和变量来拼接

var age =18;
console.log('pink老师'+ age +'岁') // pink老师18岁
// 口诀: 引引加加
案例

显示年龄 简单js交互
1.弹出一个输入框(prompt),让用户输入年龄
2.把输入的值用变量保存起来,把字符拼接起来
3.使用alert语句弹出警示框

布尔型 Boolean

有两个值: true 和false

var flag = true;
var flag1 = false;
console.log(flag + 1); // 2
console.log(flag1 + 1); // 1

undefined 未定义和Null 空数据

变量声明未赋值 就是undefined 数据类型
Null就是空数据类型

console.log(undefined + 'pink');//  undefinedpink 
console.log(undefined + 1); // NaN
console.log(null + 'pink'); // nullpink
console.log(null + 1); // 1

获取变量的数据类型

typeof属性可获取

var num = 10;
console.log(typeof num); // Number
var str = 'pink'; 
console.log(typeof str); // String
var flag = true; 
console.log(typeof flag);// Boolean
var vari = undefined 
console.log(typeof vari);// undefined
var timer = null; 
console.log(typeof timer); // object

字面量
是在源代码中一个固定值的表示方法

数据类型转换

转换为字符串类型

加号拼接字符串是重点
在这里插入图片描述

// 隐式转换
var num = 10;
console.log(num + '');

转换为数字型(重点)

记住前两个
在这里插入图片描述

var age = prompt('请输入您的年龄');
// parseInt(变量) 得到结果是整数
console.log(parseInt(age));
console.log(parseInt('3.94')); // 3 取整
console.log(parseInt('120px')); // 120    会去掉px单位
console.log(parseInt('rem120px')); // NaN
// parseFloat(变量) 得到结果是小数 浮点数

案例

1.计算年龄
在这里插入图片描述
2.简单加法器
在这里插入图片描述
转换为布尔型
在这里插入图片描述
代表空、否定的值会被转换为false,如 ’ '、0、NaN、null、undefined
其余值全部是true

作业案例

		var uname = prompt('请输入您的姓名');
        var age = prompt('请输入您的年龄');
        var sex = prompt('请输入您的性别');
        var ages = prompt('您现在多少岁了');
        var page = parseInt(ages) + 5;
        console.log(typeof page);
        console.log('您的姓名是:' + uname);
        console.log('您的年龄是:' + age);
        console.log('您的性别是'+ sex);
        console.log('据我估计,五年后,您可能' + page +'了');

运算符 operator

是用于实现赋值、比较和执行算数运算等功能的符号

算术运算符

在这里插入图片描述

// 取余 %
console.log(5 % 3); // 2
console.log(3 % 5); // 3
//  浮点数  算数运算里面会有问题
console.log(0.1 + 0.2); 
console.log(0.07 * 100);

浮点数精度问题
表达式和返回值
表达式是由数字、运算符、变量等组成的式子

console.log(1 + 1); // 2 就是返回值
// 把右边表达式计算完毕把返回值给左边

递增和递减运算符

必须和变量配合使用

前置递增运算符

口诀:先自加1,后返回值

// 想要一个变量自己加1 
var num = 1;
++num; // 类似于 num = num + 1
var p = 10;
console.log(++p + 10); // 21
++p p 这两个值是一起变化的

后置递增运算符

口诀: 先返回值,后自加

var num = 10;
num++; // 类似于 num = num + 1
var p = 10;
console.log(p++ + 10); // 20
console.log(p); // 11

小结

大多使用后置递增或递减 例如 num++,num–

比较运算符

会返回一个布尔值
在这里插入图片描述
=小结
在这里插入图片描述

逻辑运算符

返回值也是布尔值,后面开发中经常用于多个条件判断
在这里插入图片描述
逻辑: 只有两侧都为true 结果才是true
逻辑 :只有两侧都为false 结果才是false
逻辑非 :取反

短路运算(逻辑中断)

原理: 当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值

  1. 逻辑与:表达式1 && 表达式2
  2. 如果表达式1 结果为真 ,则返回表达式二
  3. 如果表达式1为假,则返回表达式1
console.log(123 && 456); // 456
console.log(0 && 1 + 2 && 456 * 789); // 0
// 如果有空的或否定的为假,其余是真的,如: 0 '' null undefined NaN
  1. 逻辑或:表达式1 || 表达式2
  2. 如果表达式1 结果为真 ,则返回表达式1
  3. 如果表达式1为假,则返回表达式2
var num = 0;
console.log(123 || num++); // 123
console.log(num); // 0

逻辑中断很重要,会影响到输出代码的值

赋值运算符

概念:用来把数据赋值给变量的运算符
在这里插入图片描述

var num = 10;
num += 2; // 类似于num = num + 2;
console.log(num); // 12

运算符优先级

在这里插入图片描述
一元运算符里面的逻辑非优先级最高
逻辑与比逻辑或优先级高

JavaScript流程控制

流程控制主要有: 顺序结构、分支结构和循环结构
在这里插入图片描述

顺序结构

程序会按照代码的先后顺序,依次执行

分支结构

根据不同的条件,执行不同的路径代码,从而得到不同的结果

if语句

// if的语法结构
if(条件表达式) {// 执行语句}
// 执行思路 如果if里面的表达式为true 则执行大括号里面的执行语句 

执行流程
在这里插入图片描述案例

// 进入网吧案例
var age = prompt('请输入您的年龄');
if(age >= 18) {
	alert('进去上网');
}

ifelse双分支语句
最终只能有一个语句执行 2选1

if (条件表达式) {
 // 执行语句1
} else {
	// 执行语句2
}
// 如果表达式结果为真,那么执行语句1; 否则 执行语句2

执行流程
在这里插入图片描述
if else if语句(多分支语句)

// 多选一的过程      else if 按实际需求来写多少个
if (条件表达式1) {
	// 语句1
} else if (条件表达式2) {
	// 语句2
}  else if (条件表达式3) {
	// 语句3
} 
else {
 // 上述条件都不成立执行此代码
}

执行流程
在这里插入图片描述

三元表达式

有三元运算符组成的式子

// 如果条件表达式为true 则返回表达式1的值
条件表达式 ? 表达式1 : 表达式2 // 语法规范

var num = 10;
var result = num > 5 ? '是的' : '不是的';
console.log(result); // 是的

案例
数字补0

var time = prompt('请您输入一个0-59之间的一个数字');
var result = time < 10 ? '0' + time : time;
alert(result);

switch语句

对变量设置一系列的特定值选项时,可以用switch

// 按实际需求来写  利用表达式的值和case后面的选项值匹配
switch (表达式) {
	case value1:
		// 执行语句1;
		break;
	case value2:
		// 执行语句2;
		break;
	default:
		// 执行最后的语句;
}

注意事项

var num = 3;
switch(num) {
	case 1:
		console.log(1)
		break;
	case 3:
		console.log(3)
		break;
}
// 表达式经常写成变量
// num的值和case里面的值相匹配的时候是全等
// 记住写break

switch语句和if else if 语句的区别
在这里插入图片描述

循环结构

循环的目的:可以重复执行某些语句

for循环

// for重复执行某些代码 通常跟计数有关系
for(初始化变量;条件表达式;操作表达式) {
	// 循环体
}
// 例子
for(var i = 1; i <= 100;i++) {
	console.log('您好');
}
// 执行过程
// 1.var i = 1这句话只执行一次
// 2.满足条件执行循环体
// 3. 最后去执行 i++ 第一轮结束
// 4.再判断是否满足条件,直到条件不满足时,退出循环

断点测试
在这里插入图片描述

// for循环可以执行相同的代码
var num = prompt('请您输入次数');
for(var i = 1; i <= num;i++) {
	console.log('我错了')
}
// for循环可以执行不同的代码 因为有计数器变量i的存在
for(var i = 1; i <= 100; i++) {
	console.log('这个人今年' + i + '岁了');
}
// for循环重复某些相同的操作

双重for循环

for(外层的初始化变量;外层的条件表达式;外层的操作表达式){ 
	for(里层的初始化变量;里层的条件表达式;里层的操作表达式)
	 {
	 // 执行语句;
	}
}
// 可以把里面的循环看做是外层循环的语句
// 外层循环一次,里层的循环执行全部
 for (var i = 1; i <= 3;i++) {
            console.log('这是外层循环第' + i  + '次');
            for (var j = 1; j <=3;j++) {
                console.log('这是里层循环第' + j  + '次');
            }
        }

小结

在这里插入图片描述

while循环

while (条件表达式) {
	// 循环体
}
// 当条件表达式为true 则执行循环体,否则 退出循环
var num = 1;
while (num <= 100) {
	console.log('How are you');
	num++;
}
// 里面也有计数器 初始化变量
// 里面也有操作表达式 完成计数器的更新 防止死循环

do while循环

do {
	// 循环体
} while (条件表达式)
// 先执行一次循环体 再判断条件
// 如条件表达式为true,则执行循环体 否则退出循环
var i = 1;
do {
	console.log('How are you');
	i++;
} while (i <= 100)

循环小结

在这里插入图片描述

continue 关键字

用于立即跳出本次循环,继续下一次循环

// 退出本次循环 继续执行剩余循环
for (var i = 1; i <= 5;i++) {
	if (i == 3) {
		continue;
	}
	console.log('我正在吃第' + i + '个包子')
}

break关键字

用于立即跳出整个循环

for (var i = 1; i <= 5;i++) {
	if (i == 3) {
		break;
	}
	console.log('我正在吃第' + i + '个包子')
}

JavaScript数组

定义:存放一组数据存储在单个变量名下的优雅方式
数组的创建方式

// 1.利用new 创建数组
var arr = new Array(); // 创建一个空数组
// 2.利用数组字面量创建数组
var arr = []; // 推荐的方式
var arr1 = [1, 2, 'pink', true]; // 可存放任意数据类型

访问数组元素

索引:用来访问数组元素的序号(数组下标从0开始)
在这里插入图片描述

var arr1 = [1, 2, 'pink', true];
console.log(arr1[2]); // pink
console.log(arr1[3]); // true
// 如没有数组元素输出结果就是undefined

遍历数组

把数组的元素从头到尾访问一次

var arr = ['red', 'green', 'blue'];
for (var i = 0; i < 3; i++) {
	console.log(arr[i]);
}

数组长度

动态检测数组元素的个数

// 语法: 数组名.length
// 改进
var arr = ['red', 'green', 'blue'];
for (var i = 0; i < arr.length; i++) {
	console.log(arr[i]);
}

案例

1.计算数组的和及2.平均值

 		var arr = [2, 6, 1, 7, 4];
        var sum = 0;
        var average = 0;
        for (var i = 0; i < arr.length; i++) {
            sum += arr[i]; // 我们加的是数组中的元素 并不是i
        }
        average = sum / arr.length;
        console.log(sum,average);

3.数组的最大值

	   var arr = [2, 6, 1, 77, 52, 25, 7];
       var max = arr[0];
       for (var i = 0; i < arr.length;i++) {
           if (arr[i] > max) {
               max = arr[i];
           }
       }
       console.log(max);

4.数组转换为分割字符串

var arr = ['red', 'green' ,'blue', 'pink'];
       var str = '';
       var sep = '!';
       for (var i = 0; i < arr.length; i++) {
           str += arr[i] + sep;
       }
       console.log(str);

数组中新增元素

// 1.通过修改length长度
var arr = ['red', 'green', 'blue'];
console.log(arr.length); // 3
arr.length = 5;
// 2.修改索引号 追加数组元素
var arr1 = ['red', 'green', 'blue'];
arr1[3] = 'pink';
console.log(arr1); // 4个
arr1[0] = 'yellow'; // 替换原来的数组元素

案例

新建一个数组

里面存放10个整数 (1-10)

 var arr = [];
       for (var i = 0; i < 10; i++) {
        //    arr = i; 切记不要直接给数组赋值  
           arr[i] = i + 1;
       }
       console.log(arr);

筛选数组

大于等于10的元素选出来,放入新数组

// 方法一
 	var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
    var newArr = [];
    var j = 0;
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] > 10) {
              // 新数组应该从0开始 依次递增
              newArr[j] = arr[i];
              j++;
          }
      }
      console.log(newArr);
 // 方法二 
   var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
      var newArr = []; // newArr.length 就是0
      for (var i = 0; i < arr.length; i++) {
          if (arr[i] > 10) {
              // 新数组应该从0开始 依次递增
              newArr[newArr.length] = arr[i];
          }
      }
      console.log(newArr);

删除指定数组元素

// 删除0
 var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
      var newArr = [];
      for (var i = 0; i < arr.length; i++) {
          if(arr[i] != 0) {
              newArr[newArr.length] = arr [i]
          }
      }
      console.log(newArr);

翻转数组

在这里插入图片描述

     var arr = ['red', 'green', 'blue', 'pink', 'purple'];
     var newArr = [];
     for (var i = arr.length - 1; i >= 0; i--) {
         newArr[newArr.length] = arr[i]
     } 
     console.log(newArr);

数组排序(冒泡排序)

把一系列的数据按照一定的顺序进行排序显示

 		var arr = [5, 4, 3, 2, 1];
        for (var i = 0; i <= arr.length - 1; i++) { 
        // 外层循环管趟数
            for (var j = 0; j <= arr.length - i -1; j++) {
             // 里层循环管交换次数
                 // 内部交换2个变量的值
                 if (arr[j] > arr[j+1]) {
                     var temp = arr[j];
                     arr[j] = arr[j+1];
                     arr[j+1] = temp;
                 }
            }
        }
        console.log(arr); // 1,2,3,4,5
       
 		var arr = [4, 5, 3, 1, 2];
        for (var i = 0; i <= arr.length - 1; i++) { 
        // 外层循环管趟数
            for (var j = 0; j <= arr.length - i -1; j++) {
             // 里层循环管交换次数
                 // 内部交换2个变量的值
                 if (arr[j] < arr[j+1]) {
                     var temp = arr[j];
                     arr[j] = arr[j+1];
                     arr[j+1] = temp;
                 }
            }
        }
        console.log(arr); // 5,4,3,2,1

JavaScript函数

函数就是封装了一段可被重复调用执行的代码块。
目的是让大量代码重复使用

 function getSum(num1,num2) {
            var sum = 0;
            for (var i = num1;i <= num2;i++) {
                sum += i;
            }
            console.log(sum);
        }
        getSum(1, 100);

函数使用

声明函数和调用函数
函数封装是把一个或多个功能通过函数的方式封装起来

// 声明函数
function 函数名() {
	// 函数体
}
// 函数名一般是动词
// 函数不调用自己不执行
函数名(); // 调用函数

 function sayHi() {
           console.log('hi~');
       }
       sayHi();

案例

利用函数计算1-100之间的累加和

			function getSum() {
            var sum = 0;
            for (var i = 1;i <= 100;i++) {
                sum += i;
            }
            console.log(sum);
        }
        getSum();

函数的参数

利用函数的参数实现函数重复不同的代码

function 函数名(形参1,形参2...) {

}
函数名(实参1,实参2...);
 function cook(aru) { // 形参aru可以看做不用声明的变量
          console.log(aru);
      }
  cook('酸辣土豆丝');
  cook('大肘子');
 // 函数的参数可以有,也可以没有,个数不受限制
 // 多个参数用逗号隔开

案例

利用函数求任意两个数之间的和

函数形参实参个数匹配

  function getSum(num1, num2) {
            console.log(num1 + num2);
        }
        console.log(1, 2); // 如果实参个数和形参的个数一致,则正常输出结果
        console.log(1, 2, 3); // 如果实参个数多于形参个数一致,会取到形参的个数
        console.log(1); // 如果实参个数少于形参个数一致,多于的形参定义为undefined 最终的结果是NaN

小结
在这里插入图片描述

函数的返回值

return语句

function 函数名() {
	return 需要返回的结果;
}
函数名();
// 函数只是实现某种功能,最终的结果需要返回给函数的调用者函数名()
// return把后面的结果 返回给函数的调用者 

 function getResult() {
           return 666;
       }
       getResult();
       console.log(getResult());

function cook(aru) { 
         return aru;
      }
      cook('大肘子');
  console.log(cook('大肘子'));

 function getSum(num1, num2) {
            return num1 + num2;
        }
        getSum(1, 2);

案例

利用函数求两个数的最大值

 function getMax(num1, num2) {
       return  num1 > num2 ? num1 : num2;
      }

求任意一个数组中的最大值

 function getArrMax(arr) { // arr接收一个数组
            var max = arr[0];
       for (var i = 0; i < arr.length;i++) {
           if (arr[i] > max) {
               max = arr[i];
           }
       }
       return max; 
        }
        var re = getArrMax([1, 2, 5, 9, 10]);
        console.log(re);

return终止函数

1.return后面的代码不被执行
2.return只能返回一个值 结果是最后一个值

 function fn(num1, num2) {
           return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
       }
       var re = fn(1, 2);
       console.log(re); // 3.如需要返回多个值,可用数组

4.函数没有return时则返回undefined
break、continue、return的区别
在这里插入图片描述

arguments的使用

当我们不确定有多少个参数传递的时候,可以用arguments来获取

 function fn() {
          console.log(arguments); 
          // arguments对象中存储了传递的所有实参
          // 遍历数组
            for (var i = 0; i < arguments.length;i++) {
         console.log(arguments[i]);
        }
      }
      fn(1, 2, 3);

伪数组 并不是真正意义上的数组
1.具有数组的length属性
2.按照索引的方式进行存储
3.它没有真正数组的一些方法

案例

利用函数求任意个数的最大值

function getMax() {
            var max = arguments[0];
            for (var i = 0; i < arguments.length; i++) {
                if(arguments[i] > max) {
                    max = arguments[i];
                }
            }
            return max;
        }
        console.log(getMax(1, 2, 3));
        console.log(getMax(1, 4, 6, 3));

函数案例

1. 利用函数封装,将数组翻转

 function reverse(arr) {
            var newArr = [];
            for (var i = arr.length - 1; i >= 0; i--) {
                newArr[newArr.length] = arr[i];
            }
            return newArr;
        }
        var arr1 = reverse([1, 3, 4, 6, 9]);
        console.log(arr1); // 9,6,4,3,1

2. 对数组排序-- 冒泡排序

function sort(arr) {
           for (var i = 0; i < arr.length - 1; i++) {
               for (var j = 0; j < arr.length - i -1; j++) {
                   if (arr[j] > arr[j + 1]) {
                       var temp = arr[j];
                       arr[j] = arr[j + 1];
                       arr[j + 1] = temp;
                   }
               }
           }
           return arr;
       }
       var arr1 = sort([1, 5, 4, 3, 6]);
       console.log(arr1); // 1,3,4,5,6

3. 判断闰年

 function isRunYear(year) {
           var flag = false;
           if (year %4 == 0 && year % 100 != 0 || year % 400 == 0) {
               flag = true;
           }
           return flag;
       }
       console.log(isRunYear(2000)); // true
       console.log(isRunYear(1999)); // false

函数可以调用另外一个函数

   // 函数可相互调用
      function fn1() {
          console.log(11);
          fn2(); // 在fn1 中调用了fn2函数
      }
      fn1();

      function fn2() {
          console.log(22);
      }

用户输入年份,输出当前2月份的天数

function backDay() {
         var year = prompt('请您输入年份:');
         if (isRunYear(year)) {
             alert('当前有29天');
         } else {
             alert('当前有28天');
         }
     }
     backDay();

     // 判断是否是闰年的函数
     function isRunYear(year) {
           var flag = false;
           if (year %4 == 0 && year % 100 != 0 || year % 400 == 0) {
               flag = true;
           }
           return flag;
       }

函数的2种声明方式

命名函数

// 函数表达式 语法 匿名函数
var 变量名 = function() {};
变量名(); // 调用
var fun = function() {
	console.log('我是函数表达式');
}
fun(); // fun是变量名 不是函数名
// 函数表达式也可以进行传递参数

作用域

代码名字(变量)在某个范围内起作用和效果
目的为了提高程序的可靠性,减少命名冲突
js的作用域(es6)之前 : 全局作用域 和局部作用域
全局作用域: 整个script标签 或是一个单独的js文件
局部作用域: 在函数内部就是 只在函数内部起效果和作用

var num = 10;
console.log(num);
function fn() {
	var num = 20;
	console.log(num);
}
fn();

变量分为全局变量和局部变量
全局变量: 在全局作用域下的变量
如果在函数内部没有声明直接赋值的也是全局变量(不推荐)
局部变量: 在函数中的变量
函数的形参也是局部变量

 function fun() {
         var num1 = 10;
         num2 = 20;
     }
     fun();
     console.log(num2);

js没有块级作用域 (es6之前)
块级作用域 {} if {} for{}

作用域链

内部函数访问外部函数的变量,采取的是链式查找的方法

 var num = 10;
        function fn() { // 外部函数
            var num = 20;

            function fun() { // 内部函数
                console.log(num); // 20
            }
            fun();
        }
        fn();

预解析

js引擎运行js分为两步:预解析 代码执行
js引擎会把js里面的var 还有 function 提升到当前作用域的最前面
代码执行 按从上往下执行
预解析分为 变量预解析和函数预解析
变量提升 把所有的变量声明提升代当前的作用域最前面 不提升赋值操作

举报

相关推荐

0 条评论