JavaScript第三天

1 JavaScript预解析

1.1 预解析

我们js引擎运行js分为两步: 预解析代码执行

(1). 预解析js引擎会把js里面所有的var还有function提升到当前作用域的最前面
(2). 代码执行 按照代码书写的顺序从上往下执行

1.2 变量预解析和函数预解析

预解析分为变量预解析(变量提升) 和函数预解析(函数提升)

(1) 变量提升,就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作,所有var

(2)函数提升,就是把所有的函数声明提升到当前作用域的最前面不调用函数
,所有函数

//变量提升
console.log(num);//unfined
var num = 10;

//相当于执行了一下代码,先预解析,剩下的代码依次罗列
var num;
console.log(num);//unfined
num = 10;
//变量提升
funn();//报错
var fun = function() {
	console.log(22);
	}
//相当于执行了以下代码
var fun;
funn();//报错
fun = function() {
 console.log(22);
 }
//函数提升
fn();
function fn() {
 console.log(11);
 }
//相当于执行了以下代码

function fn() {
 console.log(11);
 }
fn();

1.3 预解析案例

案例一:

var num = 10;
fun();
function fun() {
	console.log(num);
	var num = 20;
}
//相当于执行以下代码
//外部变量var 和函数, 提到当前作用域最前面,剩下的代码按顺序排列

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

//
var num;
function fun() {
 var num;
 console.log(num);
 num = 20;
}
num=10;
fun();
//输出结果是undefined

案例二:

        f1();
        console.log(c);
        console.log(b);
        console.log(a);
        function f1() {
            var a = b = c = 9;
            console.log(a);
            console.log(b);
            console.log(c);
        }
        //相当于下面这些代码
        function f1() {
            var a;
            a = b = c = 9;
            //相当于var a = b = c = 9;b和c直接赋值  没有var 声明 当全局变量看
            //集体声明 var a = 9; b = 9; c = 9;
            console.log(a);
            console.log(b);
            console.log(c);
        }
        f1();
        console.log(c);
        console.log(b);
        console.log(a);

2 JavaScript对象

2.1 对象

2.1.1什么是对象?

现实生活中:万物皆对象,对象是一个具体的事物 ,看得见摸得着的实物。例如,.一本书、一辆汽车、 一个人可以是”对象”, 一个数据库、一张网页、 一个与远程服务器的连接也可以是“对象”。

在JS中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如,字符串,数值,数组,函数等。

对象是由属性方法组成的

  • 属性:事物的特征,在对象中用属性来表示(常用名词)
  • 方法:事物的行为,在对象中用方法来表示(常用动词)

2.1.2 为什么需要对象

  • 保存一个值时,可以使用变量,
  • 保存多个值(一组值)时,可以使用数组,
  • 保存一个人的完整信息
    JS中的对象表达结构更清晰,更强大

2.2 创建对象的三种方式

在JS中,现阶段我们可以采用三种方式创建对象(object):

  • 利用字面量创建对象
  • 利用new Object创建对象
  • 利用构造函数创建对象

2.2.1 利用字面量创建对象

对象字面量:就是花括号{}里面包含了表达这个具体事务(对象)的属性和方法。

1、利用对象字面量创建对象
  • 里面的属性或者方法,我们采取键值对的形式,键:值---->属性名:属性值
  • 多个属性或方法中间用逗号隔开,最后一个可以不用跟逗号
  • 方法冒号后面跟的是一个匿名函数
2、使用对象
  • 调用对象的属性,我们采取对象名.属性
  • 调用对象的属性,我们采取对象名['属性名']
  • 调用对象的方法, 我们采取对象名.方法名()
//1、利用对象字面量创建对象
var obj = {};//创建了一个空的对象
var obj = {
    uname: '张三丰',
    age:18,
    sex:'男',
    sayHi: function() {
        console.log('hi~');
    }
}
//(1)里面的属性或者方法,我们采取键值对的形式,键:值---->属性名:属性值
//(2)多个属性或方法中间用逗号隔开

//2、调用对象的属性
//(1)(不用加引号)对象名.属性
console.log(obj.uname);
//(2)(加引号)对象名['属性名']
console.log(obj['uname']);

//3、调用对象的方法  对象名.方法名()  千万别忘记添加小括号
obj.sayHi();

3、变量、属性、函数、方法总结
  • 变量:单独声明赋值,单独存在

  • 属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征

  • 函数:单独存在的,通过"函数名()”的方式就可以调用

  • 方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可以调用,方法用来描述该对象的行为和功能。

2.2.2 利用new Object创建对象

和创建数组差不多var arr = new Array();
创建

  • var obj = new Object();//创建一个空的对象
  • obj.uname = ‘张三丰’;//利用追加的方式添加属性
  • 利用等号 = 赋值的方法 添加对象的属性和方法
  • 每个属性和方法之间用分号结束

调用

  • console.log(obj.uname);//对象名.属性
  • console.log(obj[‘uname’]);//对象名[‘属性名’]
  • obj.sayHi();//对象名.方法名(),千万别忘记添加小括号
//利用`new Object `创建对象
var obj = new Object();//创建一个空的对象
obj.uname = '张三丰';//利用追加的方式添加属性
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
        console.log('hi~');
    }
}
//(1)利用等号 = 赋值的方法 添加对象的属性和方法
//(2)每个属性和方法之间用分号结束

2.2.3 利用构造函数创建对象

为什么使用构造函数,:因为前面两种创建对象的方式,一次只能创建一个对象

  • 我们可以利用函数的方式,重复这些相同的代码,我们就把这个函数称为构造函数
  • 里面封装的不是代码,而是对象
  • 构造函数,就是把我们对象里面一些相同的属性和方法抽象出来,封装到函数里面
function 构造函数名() {
            this.属性 =;
            this.方法 = function () { }
        }
     1.构造函数名字首字母要大写        
     
     2.我们构造函数不需要return,就可以返回结果        
     
     3.我们调用构造函数,必须使用new        
     
     4.我们只要new Star(),调用函数就创建了一个对象        
     
     5.我们的属性和方法前面必须添加this
        // 我们需 要创建四大天王的对象相同的属性: 名字年龄性别相同的方法: 唱歌
        // new构造函数名();
        function Star(uname, age, sex) {
            this.name = uname;
            this.age = age;
            this.sex = sex;
            this.sing = function(sang) {
                console.log(sang);
            }
        }
        var ldh = new Star('刘德华', 18, '男');//调用函数返回的一个对象(object),只要new 构造函数名就可以生成对象
        console.log(ldh.name);//ldh的名字
        console.log(ldh['age']);
        ldh.sing('冰雨')
        var zxy = new Star('张学友', 19, '男');
        console.log(zxy.name);//zxy的名字
        console.log(zxy['age']);//zxy的年龄

2.2.4 构造函数和对象

  • 构造函数,如Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类
  • 创建对象,如new Stars() ,特指某一个,通过new 关键字创建对象的过程我们称为对象实例化

2.3 new关键字

new关键 字执行过程

    1. new构造函数可以在内存中创建了一个空的对象
    
    2.this就会指向刚才创建的空对象
    
    3.执行构造函数里面的代码给这个空对象添加属性和方法
    
    4.返回这个对象
        function Star(uname, age, sex) {
            this.name = uname;
            this.age = age;
            this.sex = sex;
            this.sing = function(sang) {
                console.log(sang);
            }
        }
        var ldh = new Star('刘德华', 18, '男');

2.4 遍历对象属性

for...in用于对数组或者对象的属性进行循环操作
for...in遍历对象

for (变量 in 对象) {
}
    <script>
        var obj = {
            name:'老师',
            age: 18,
            sex: '男',
        }
        for (var k in obj) {
            console.log(k);//k变量输出,得到的是属性名
            console.log(obj[k]);//obj[k] 得到的是属性值
        }
        //我们使用 for in 里面的变量 我们喜欢写 k 或者 key
    </script>

3 JavaScript 内置对象

3.1 内置对象

  • JavaScript中的对象分为3种:自定义对象、内置对象、浏览器对象
  • 前两种对象是JS基础,属于ECMAScript;
  • 第三种浏览器对象属于我们JS独有的,在JS API中说明
  • 内置对象:就是指JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或者最基本而有必要的功能(属性和方法)
  • 内置对象最大的优点是:帮助我们快速开发
  • JS提供了多个内置对象:Math、Date、Array、String等。

3.2 查文档

MDN和W3C
学习一个内置对象的使用,只要学会其常用成员的使用即呵, 我们可以通过查文档学习,可以通过MDN、W3C来查询。

Mozilla开发者网络( MDN )提供了有关开放网络技术( Open Web )的信息,包括HTML、CSS和万维网及HTML5 应用的API.

MDN: https://developer.mozilla.org/zh-CN

3.3 Math对象

Math数学对象不是一个构造函数,所以我们不需要new来调用而是直接使用里面的属性和方法即可。

    <script>
        // Math数学对象不是一个构造函数,所以我们不需要new来调用而是直接使用里面的属性和方法即可
        console.log(Math.PI); //一个属性圆周率 3.141592653589793
        console.log(Math.max(1, 99, 3)); // 99
        console.log(Math.max(-1, -10)); // -1
        console.log(Math.max(1, 99, 'pink老师')); // NaN
        console.log(Math.max()); // - Infinity
    </script>

3.3.1 封装自己的数学对象

    <script>
        //利用对 象封装自己的数学对象里面有PI最大值和最小值
        var myMath = {
            PI: 3.141592653,
            max: function () {
                var max = arguments[0];
                for (var i = 1; i < arguments.length; i++) {
                    if (arguments[i] > max) {
                        max = arguments[i];
                    }
                }
                return max;
            },
            min: function() {
                var min = arguments[0];
                for (var i = 1; i < arguments.length; i++) {
                    if (arguments[i] < min) {
                        min = arguments[i];
                    }
                }
                return min;
            }
        }
        console.log(myMath.PI);
        console.log(myMath.max(1, 5, 9)); 
        console.log(myMath.min(1, 5., 9));
    </script>

3.3.2 Math概述

Math对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用Math中的成员。

Math.PI                      //圆周率
Math. floor()                //向下取整
Math.ceil ()                 //向上取整
Math. round()                //四舍五入版就近取整   注意-3.5    结果是-3(.5往大了取)
Math.abs ()                  //绝对值
Math.max() /Math.min()      // 求最大和最小值
    <script>
        //1.绝对值方法
        console.log(Math.abs(1));//绝对值就是1
        console.log(Math.abs(-1));//绝对值就是1
        console.log(Math.abs('-1'));//1,隐式转换,会把字符串型 -1 转换为数字型
        console.log(Math.abs('老师'));//NaN
        //2.三个取整方法
        //(1)Math.floor() 向下取整 ,往最小了取
        console.log(Math.floor(1.1));//1
        console.log(Math.floor(1.9));//1
        //(2)Math.ceil() 向上取整 ,往最大了取
        console.log(Math.ceil(1.1));//2
        console.log(Math.ceil(1.9));//2
        //(3)Math.round() 其他数字都是四舍五入,但是.5例外,它往最大了取
        console.log(Math.round(1.1));//1
        console.log(Math.round(1.5));//2
        console.log(Math.round(1.9));//2
        console.log(Math.round(-1.5));//-1
        console.log(Math.round(-1.9));//2
    </script>

3.3.2 随机数方法 random()

    <script>
        // 1.Math对 象随机数方法random() 返回一个随机小数 e =< X < 1 
        //2.这个方法里面不跟参数
        console.log(Math.random());
        // 4.我们想要得到两个数之间的随机整数并且包含这2个整数
        // Math.floor(Math.random() * (max - min + 1)) + min;
        function getRandom(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        }
        console.log(getRandom(1, 10));
        //5.随机点名
        var arr = ['张三', '张三丰','张三疯子','李四','李思思','pink老师'];
        //console.log(arr[0]);
        console.log(arr[getRandom(0, arr.length-1)]);
    </script>

3.4 Date日期对象

3.4.1 Date概述

  • Date对象和Math对象不太一样,他是一个构造函数,我们需要实例化后才可以使用
  • Date实例用来处理日期和时间

3.4.2 Date()方法的使用

1、获取当前时间必须实例化
var now = new Date();
 console.log(now);
    <script>
        //Date()日期对象是一个构造函数必须使用new来调用创建我们的日期对象
        var arr = new Array(); //创建一个数组对象
        var obj = new Object(); //创建了一个对象实例
        // 1.使用Date如果没有参数返回当前系统的当前时间
        var date = new Date();
        console.log(date);
        // 2.参数常用的写法 数字型 2019, 10, 01 或者是字符串型'2019-10-1 8:8:8'
        var date1 = new Date (2019, 10, 1);
        console.log(date1);//返回的式11月不是10月
        var date2 = new Date ('2019-10-1 8:8:8');
        console.log(date2);
    </script>
2、Date 构造函数的参数

如果括号里面有时间,就返回参数里面的时间,例如日期格式字符串为’2019-5’(最常用),或者new Date(‘2019/5/1’)

3.4.3 日期格式化

在这里插入图片描述

    <script>
        // 格式化日期 年月日
        var date = new Date();
        console.log(date.getFullYear()); //返回当前日期的年2019
        console.log(date.getMonth() + 1); //月份返回的月份   小1个月   记得月份+1 呦\
        console.log(date. getDate()); //返回的是几号
        console.log(date.getDay()); // 3周一返回的是 1周六返回的是6但是周日返回的是0
        //我们写一个2019年 5月1日星期三
        var year = date.getFullYear();
        var month = date.getMonth() + 1;
        var dates = date.getDate();
        var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
        var day = date.getDay();
        console.log('今天是:'+year+'年'+month+'月'+dates+'日' + arr[day]);
    </script>

在这里插入图片描述

    <script>
        var date = new Date();
        console.log(date.getHours()); //时
        console.log(date.getMinutes()); //分
        console.log(date.getSeconds()); //秒
        //要求封装个函数返回 当前的时分秒格式08:08:08
        function getTime() {
            var time = new Date();
            var h = time.getHours();
            h = h < 10 ? '0' + h : h;
            var m = time.getMinutes();
            m = m < 10 ? '0' + m : m;
            var s = time.getSeconds();
            s = s < 10 ? '0' + s : s;
            return h + ':' + m + ':' + s;
        }
        console.log(getTime());
    </script>

在这里插入图片描述

3.4.4 获取日期的总的毫秒(时间戳)

    <script>
        //获得Date总的毫秒数(时间戳)不 是当前时间的毫秒数  而是距离1970年1月1号过了多少毫秒数
        // 1.通过valueOf() getTime()
        var date = new Date();
        console.log(date.valueOf()); //就是我们现在时间距离1970.1.1总的毫秒数
        console.log(date.getTime());
        // 2.简单的写法(最常用的写法)
        var date1 = +new Date(); // +new Date() 返回的就是总的毫秒数
        console.log(date1);
        // 3. H5新增的获得总的毫秒数
        console.log(Date.now()); 
    </script>

3.5 数组对象

3.5.1 数组对象的创建

两种方式:

  • 字面量方式
  • new Array()
    <script>
        //创建数组的两种方式
        // 1.利用数组字面量
        var arr = [1, 2, 3];
        console.log(arr[0]);
        // 2.利用new Array( )
        //var arr1=newArray();//创建了一个空的数组
        // var arr1 = new Array(2);
        //这个2表示数组的长度为2里面有2个空 的数组元素
        var arr1 = new Array (2, 3); //等价于[2,3] 这样写表示里面有2个数组元素是2和3
        console.log(arr1);
    </script>

3.5.2检测是否为数组

  • arr instanceof Array
  • Array. isArray(参数)
        // (1) instanceof 运算符它可以用来检测是否为数组
        var arr = [];
        var obj = {};
        console.log(arr instanceof Array);
        console.log(obj instanceof Array);
        // (2) Array. isArray(参数); H5新增的方法,ie9以上版本支持
        console.log(Array.isArray(arr));
        console.log(Array.isArray(obj));

3.5.3 添加删除数组元素的方法

在这里插入图片描述
添加

        //添加删除数组元素方法
        // 1. push() 在我们数组的末尾添加一个或者 多个数组元素  push推
        var arr = [1, 2, 3];
        // arr . push(4, 'pink');
        console .log(arr.push(4, 'pink'));
        console.log(arr);
        // (1) push 是可以给数组追加新的元素
        // (2) push() 参数直接写数组元素就可以了
        // (3) push完毕之后,返回的结果是新数组的长度
        // (4) 原数组也会发生变化
        // 2. unshift 在我们数组的开头添加一个或者多个数组元素
        console.log(arr .unshift('red', 'purple' ));
        console.log(arr);
        // (1) unshift 是可以给数组前面追加新的元素
        // (2) unshift() 参数直接写数组元素就可以了
        // (3) unshift完毕之后,返回的结果是新数组的长度
        // (4) 原数组也会发生变化

删除

        //3.pop()它可以删除数组的最后一个元素
        console .log(arr.pop());
        console.log(arr);
        // (1) pop是可以删除数组的最后一个元素记住一 次只能删除一 个元素
        // (2) pop() 没有参数
        // (3) pop完毕之后,返回的结果是删除的那个元素
        // (4) 原数组也会发生变化
        // 4. shift() 它可以删除数组的第一个元素
        console.log(arr.shift());
        console.log(arr);
        //(1)shift是可以删除数组的第一个元素记住一次只能删除一个元素
        // (2) shift() 没有参数
        // (3) shift完毕之后,返回的结果是删除的那个元素
        // (4) 原数组也会发生变化

3.5.4 数组排序

在这里插入图片描述

    <script>
        // 数组排序
        // 1.翻转数组
        var arr = ['pink', 'red', 'blue']; 
        arr.reverse();
        console.log(arr);
        //2.数组排序(冒泡排序)
        var arr1 = [13, 4, 77, 1, 7];
        arr1.sort(function (a, b) {
            // return a - b;升序的顺序排列
            return b - a; //降序的顺序排列
        });
            console.log(arr1);
    </script>

3.5.5 数组索引方法

在这里插入图片描述

        //返回数组元素索引号方法 indexOf(数组元素) 作用就是返回该数组元素的索引号从前面开始查找
        //它只返回第一个满足条件的索引号
        // 它如果在该数组里面找不到元素, 则返回的是-1
        //var arr=['red',' green', 'blue', 'pink', 'blue'];
        var arr = ['red', 'green', 'pink'];
        console.log(arr.indexOf('blue'));
        //返回数组元素索引号方法lastIndex0f(数组元素) 作用就是返回该数组元素的索引号从后面开始查找
        var arr = ['red',' green','blue', 'pink', 'blue'];
        console.log(arr .lastIndexOf('blue')); // 4

3.5.6 数组转换为字符串

在这里插入图片描述

    <script>
        //数组转换为字符串
        // 1. toString() 将我们的数组转换为字符串
        var arr = [1, 2, 3];
        console.log(arr.toString()); //1, 2, 3
        //2. join(分隔符)
        var arr1 = ['green', 'blue', 'pink'];
        console.log(arr1.join()); // green, blue, pink
        console.log(arr1.join('-')); // green - blue - pink
        console.log(arr1.join('&')); // green & blue & pink
    </script>

在这里插入图片描述

3.6 字符串对象

3.6.1基本包装类型

为了方便操作基本数据类型, JavaScript 还提供了三个特殊的引用类型: String、Number和Boolean.

基本包装类型就是简单数据类型包装成为复杂数据类型**,这样基本数据类型就有了属性和方法**。

//下面代码有什么问题?
var str = 'andy' ;
console. log (str. length);

按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为js会把基本数据类型包装为复杂数据类型,其执行过程如下:

// 1.生成临时变量,把简单类型包装为复杂数据类型var temp = new String('andy');
// 2.赋值给我们声明的字符变量
str = temp;
// 3.销毁临时变量
temp = null;

3.6.2 字符串的不可变

指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间

3.6.3根据字符串返回位置

字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串

str.indexOf(要查找的字符串)
var str = ‘改革春风,春天’
console.log(str.indexOf(‘春’));//根据字符返回位置
str.indexOf('要查找的字符串',[起始的位置])
在这里插入图片描述

3.6.4 根据位置返回字符

在这里插入图片描述

    <script>
        //根据位置返回字符
        // 1. charAt(index) 根据位置返回字符
        var str = 'andy';
        console.log(str.charAt(3));
        //遍历所有的字符
        for (var i = 0; i < str.length; i++) {
            console.log(str.charAt(i));
        }
        // 2. charCodeAt(index) 返回相应索引号的字符ASCII值目的: 判断用户按下了那个键
        console.log(str.charCodeAt(0)); // 97
        // 3. str[index] H5新增的
        console.log(str[0]);  // a
    </script>

一个对象是否有该属性 对象[‘属性名’]

3.6.5 字符串操作方法

在这里插入图片描述

        //字符串操作方法
        // 1. concat(字符串1',字符串2....)
        var str = 'andy';
        console.log(str.concat('red'));
        // 2. substr( ' 截取的起始位置', '截取几个字符');
        var str1 = '改革春风吹满地';
        console.log(str1.substr(2, 2)); //第一个2是索引号的2从第几个开始第 二个2是取几个字符

        // 1.替换字符replace('被替换的字符','替换为的字符) 它只会替换第一个字符
        var str = ' andyandy';
        console.log(str.replace('a', 'b'));
        //有一个字符串' abcoefoxyozzopp' 要求把里面所有的o,替换为* 
        var str1 = 'abcoefoxyozzopp ';
        while (str1.indexOf('o') !== -1) {
            str1 = str1.replace('o', '*');
        }
        console.log(str1);
        // 2.字符转换为数组splif('分隔符')
        //前面我们学过join把数组转换为字符串
        var str2 = 'red, pink, blue';
        console.log(str2.split(','));
        var str3 = 'red&pink&blue';
        console.log(str3.split('&'));

toUpperCase();//转化为大写
toLowerCase();//转换为小写

4 JavaScript 简单数据类型和复杂数据类型

4.1 简单类型与复杂类型

简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。

  1. 值类型: 简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型 string , number,boolean ,undefined,null
  2. 引用类型: 复杂数据类型,在存储时变量中存储的仅仅是地址(引用) ,因此叫做引用数据类型,通过new关键字创建的对象(系统对象、自定义对象) , 如Object, Array, Date等

4.2 堆和栈

堆栈空间分配区别:

  1. 栈(操作系统) :由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
    简单数据类型存放到栈里面
  2. 堆(操作系统) :存储复杂类型(对象) , 一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
    复杂数据类型存放到堆里面
    js里面没有堆和栈

4.3 简单类型和 复杂类型的内存分配

//简单数据类型null 返回的是个空的对象,object
var timer = nu11;
console .1og(typeof timer);//object
//如果有个变量我们以后打算存储为对象,暂时没想好放啥, 这个时候就给nul1
// 1.简单数据类型是存放在栈里面里面直接开辟个空间存 放的是值
// 2.复杂数据类型首先在栈里面存放地址十六进制表示 然后这个地址指向堆里面的数据

4.4 简单类型传参

函数的形参也可以看做是一个变量 ,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈.
空间里的值复制了一份给形参 ,那么在方法内部对形参做任何修改,都不会影响到的外部变量。

4.5 复杂类型传参

函数的形参也可以看做是一个变量。当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值