JS基础语法

JavaScript基础语法

变量

  • 变量提升
    • js中,变量另一个不同寻常的地方,你可以先使用变量稍后再声明变量而不会引发异常。
    • 这一概念称为变量提升,js的变量感觉上是被"提升"或移动到了函数或语句的最前面,此时引用这个变量,将返回undefined值
a = 1; // 隐式定义,不会声明提升;注意不要使用,请遵守严格模式的定义格式

// 严格模式
console.log(a) // 不抛异常,var定义会把变量提升到当前全局作用域后者函数作用域
var a; // 使用变量不不声明变量;变量提升
console.log(b) // 抛异常,除去var定义的变量,其余变量必须先定义,后引用
let b; // 使用变量而不声明变量;不会变量提升
console.log(b)
const c = 100; // 使用常量定义时必须声明变量,且之后常量不能再覆盖
console.log(c)

a = 1;
a = 2; // JS中没有重新赋值即定义一说,只有覆盖
b = 'abc';
b = c + c; // 使用常量
console.log(a,b,c);

// c = 200; // 常量不能再次指向其他对象,抛TypeError: Assignment to constant variable.

弱类型语言

隐式类型转换原则不要死记,记不清就实验;严格模式,建议显示的类型转换

// 类型转换
// 弱类型 -- 不需要强制类型转换,隐式类型转换
// string
console.log('==='.repeat(3),'sting','==='.repeat(3)); /*与字符串相加,均隐式转换成string*/
console.log(a = 3 + 'js',typeof(a)); // 3js,字符串凭借
console.log(a = null + 'js',typeof(a)); // nulljs
console.log(a = undefined + 'js',typeof(a)); // undefinedjs
console.log(a = true + 'js',typeof(a)); // turejs

// number
console.log('==='.repeat(3),'number','==='.repeat(3));
// NaN,Not A Number,类型为number
// null,false隐式转为0,true隐式转为1
console.log(a = null + 8,typeof(a));
console.log(a = undefined + 8,typeof(a)); // undefined转换成一个对应的数字,只能为NaN
console.log(a = true + 8,typeof(a));

console.log(a = null - 8,typeof a);
console.log(a = 'abc' - 8,typeof a); // string不能转换成一个对应的数字,只能为NaN
console.log(a = true - 8,typeof a);

// boolean
console.log('==='.repeat(3),'bool','==='.repeat(3));
console.log(a = null + true,typeof a); // 隐式转为number进行算数运算
console.log(a = undefined + false,typeof a); // NaN值不能进行加法运算
console.log(a = null & true,typeof a); // 隐式转为number进行位运算
console.log(a = undefined & true,typeof a); // 0 number,NaN竟然以0进行为运算

console.log(a = null - true,typeof a);
console.log(a = undefined - false,typeof a); // NaN值不能进行减法运算

// 短路运算,返回短路时的对象类型,不会隐式转换
console.log('==='.repeat(3),'短路','==='.repeat(3))
// 与
console.log(a = null && true,typeof a);
console.log(a = false && true,typeof a);
console.log(a = true && 'js',typeof a);
// 或
console.log(a = true || 'js',typeof a);
console.log(a = false || 'js',typeof a);
console.log(a = null || 'js',typeof a);
console.log(a = {} || 'js',typeof a); // 注意:{}在js中为真,注意和python的区别
console.log(a = [] || 'js',typeof a); // 注意:[]在js中为真,注意和python的区别

// null
console.log('==='.repeat(3),'null','==='.repeat(3))
console.log(a = null + undefined,typeof a ) // 隐式转为number,NaN

string

// js中没有三引号,三引号是python的个性
let a = 'ab\'c' // 反斜杠\为转义字符
let b = '"135'  
let c = `line1 
line2
line3
` /* ES6提供了反引号定义字符串,可以支持多行和插值 */
console.log(a,b,c)


// 反引号``插值
// 一个变量只能使用关键字定义一次,之后不能再次使用let、var、const定义
let name = 'tom', age = 19
console.log(`Hi,my name is ${name}, age is ${age}`) // js,类似于python3.6新增的f前缀

name = 'jerry',age = 20 
console.log('Hi my name is ${name}, age is ${age}') 
// name = 'tom'
// age = 19
// f'my name is {name},age is {}' python中f插值的用法

// 转义字符
console.log('\\') /* 反斜杠 */
console.log('\060') /* 由0 ~ 377最多三位八进制数表示的ASCII字符 */
console.log('\x31','\x41','\x61') // 由0 ~ ff最多两位十进制数表四的ASCII
console.log('\u0061') // 由四位十六进制表示的Unicode字符
console.log('\u{00061}') // 此处存疑

字符串拼接

let test = 'javascript';

console.log(test.charAt(2)); // v
console.log(test[2]); // v
console.log(test.toUpperCase()); // 大写
console.log(test.toLowerCase()); // 小写
console.log(test.concat('-test')); // 字符串拼接

// 切片slice(start?: number, end?: number)
// start,起始索引;end,终止索引;前闭后开,且没有步长
console.log(test.slice(3)); // 索引3 ~ 末尾
console.log(test.slice(3,5)); // 前闭后开
// console.log(test.slice(-1,-3)); // 不能从右往左且,抛异常
console.log(test.slice(5,-1)) // 支持负索引

let url = test.concat('.com.cn');
console.log(url.split('.')); // 数组,效果同python的split
// substr(from: number, length?: number)
console.log(url.substr(2,5)); // from索引2,取length为5的子字符串长度
// substring(start: number, end?: number)
console.log(url.substring(2,5)); //  start索引2,end索引5,效果同slice

url = 'js.com.com';
console.log(url.indexOf('ed')); // 查询不到,返回-1
console.log(url.indexOf('com')); // 3,查到第一个匹配值就返回索引
console.log(url.indexOf('com',4)); // 7,第二参数设置查询开始索引

url = '   this is \r\n test   ';
console.log(url.trim()); // 去除两端的空白字符
console.log(url.trimLeft()); // 非标准函数,不要使用
console.log(url.trimRight()); // 非标准函数,不要使用

url = `---`;
console.log(url.repeat(30)); // 字符串重复指定的次数
console.log(test.replace('script','')); // 指定字符串替换为''

number

console.log(0b111); // 二进制,7
console.log(0B111); // 二进制,7
console.log(0o755); // 八进制,493
console.log(0755); // 隐式八进制
console.log(0x7f); // 十六进制127
console.log(0Xff); // 十六进制255
console.log(1E3); // 1000
console.log(2e-2); // 0.02,科学计数法:2e-2 = 2 * (10 ** -2)
console.log(1.7E+3); // 1700
console.log(1.7E3); // 1700

var biggestNum = Number.MAX_VALUE;
var smallestNum = Number.MIN_VALUE;
var infiniteNum = Number.POSITIVE_INFINITY;
var negInfiniteNum = Number.NEGATIVE_INFINITY;
var notAum = Number.NaN;
console.log(biggestNum,smallestNum,infiniteNum,negInfiniteNum,notAum);

// 内置数学对象Math
console.log(Math.PI); // Π值
console.log(Math.abs(-1)); // 绝对值
console.log(Math.log2(16)); // 以2为低,16的对数
console.log(Math.sqrt(2)); // 2 ** 0.5
console.log(2 ** 0.5);

// 随机取值技巧
console.log(Math.random()) // (0,1)随机取值
console.log(Math.random() * 10) // (1,10)随机取值
console.log((Math.random() * 9) + 1) // (1,10)

Symbol

// ES6提供Symbol类型,内建原生类型
let sym1 = Symbol('key1')
let sym2 = Symbol('key2')
let sym3 = Symbol('key3')
// console.log(sym2 == sym3) // false; symbol值是唯一的,参考Python的类实例

// 作为对象的属性key,起隐藏对象属性的作用
console.log(sym1.valueOf());
let a = {
    sym1, /* 键为'sym1',值为sym1.valueOF() */
    'sym':sym1.valueOf, // [Function: valueOf]
    'sym2':'ttt', // sym2: 'ttt'
    sym3:'abc', // sym3: 'abc',
    [sym2]: /* Symbol对象作key,注意使用中括号,这个key唯一且有隐藏的作用 */ 'xyz' // [Symbol(key2)]: 'xyz',
};

for (attr in a){
    console.log(a[attr])
}; // key为Symbol对象无法访问到

console.log(a)

// 构建常量
// 以前的用法
var COLOR_RED = 'RED';
var COLOR_BLUE = 'BLUE';
var COLOR_GREEN = 'GREEN';
// 现在构建常量的方法,通过变量名识别,此处存疑
const COLOR_RED = Symbol();
const COLOR_BLUE = Symbol();
const COLOR_GREEN = Symbol();

运算符

算数运算符

// 运算符
// + - * /等运算符和python一样
console.log(1 / 2); // 自然除,浮点型
console.log(1 / 0); // 注意:不抛异常,返回Infinity
console.log(5 % 3); // 2

// parseInt(),截取整数部分
console.log(parseInt(1/2));
console.log(parseInt(3/2));
console.log(parseInt(-1/2));
console.log(parseInt(0.5),parseInt(0.6),parseInt(0.4));
console.log(parseInt(1.5),parseInt(1.6),parseInt(1.4));
console.log(parseInt(-1.4),parseInt(-1.5),parseInt(-1.6));

console.log(Math.ceil(1.5),Math.ceil(1.6),Math.ceil(1.4));
console.log(Math.ceil(-1.5),Math.ceil(-1.6),Math.ceil(-1.4)); // Math.ceil向上取整
console.log(Math.floor(1.4),Math.floor(1.5),Math.floor(1.6));
console.log(Math.floor(-1.4),Math.floor(-1.5),Math.floor(-1.6)); // Math.floor向下取整

// Math.round,4舍,取绝对值更小的值;6入,取绝对值更大的值;5,取数轴横坐标右边离自己最近的整数
console.log(Math.round(1.4),Math.round(1.5),Math.round(1.6)); 
console.log(Math.round(2.4),Math.round(2.5),Math.round(2.6));

console.log(Math.round(-1.4),Math.round(-1.5),Math.round(-1.6));
console.log(Math.round(-2.4),Math.round(-2.5),Math.round(-2.6));

++,不入栈加1;–,不入栈减1

let i = 0
console.log(i++); // i++;++在变量右边,先引用变量,后增加1
console.log(i);  // 注意,变量i指向的数值已经发生变化
console.log(++i); // ++i;++在变量左边,变量先增加1,后引用变量

console.log(i--); // i--,使用原理同i++
console.log(i); // 注意,变量i指向的数值已经发生变化
console.log(--i);// --i,使用原理同++i

// ++挑战题
let a = ++i+i+++i+++i;
i = 0;
let b = i+++i+++i+++i+++i;
// 分析:单目运算符优先级高于双目运算符
// a: ++i+i+++i+++i -> ++i + i++ + i++ + i -> 1 + 1 + 2 + 3
// b: i+++i+++i+++i+++i -> i++ + i++ + i++ + i++ +i -> 0 + 1 + 2 + 3 + 4
// 注意:i++,先用i,不会使用i++之后的值
console.log(a); // 7
console.log(b); // 10

比较运算符

  • js中不同类型之间因为隐式类型转换,可以进行比较;
    • >、<、>=、<= 使用原则参考python

注意:为了健壮的代码,不要使用隐式转换,请使用严格比较

// 不同类型隐式比较,不建议
// console.log(100 > 200); // false
// console.log(100 > '200'); // js中,尝试将不同类型隐式转为number
// console.log(100 > '50');
// console.log(100 > true);
// console.log(100 > undefined); // NaN,比较失败
// console.log(100 > '2a'); // 隐式转换'2a'为string失败为Nan,比较失败

// 宽松比较,隐式类型转换
console.log(100 == '100') // 将string,隐式转为number比较,ture
console.log('100' == '100')
console.log(20 != '20') // false

// 严格比较,不进行隐式类型转换;
// 书写健壮的代码,提倡使用严格比较
// ===,!==
console.log(300 === '300') // false,不会进行隐式类型转换,代码安全
console.log('200' === '200') 
console.log(300 !== '300') // true

逻辑运算符

  • 与 &&; 或 ||; 非 !;
  • 使用原则参考python,支持短路
console.log({} && false); // false
console.log({} || fasle); // js中{}为真,返回{}
console.log({} && [] && false); // js中[]为真,返回false
console.log([] || {} || false); // false

位运算

// 位运算,符号和python一样
console.log(4 & 1); // 0,位与判断偶数的技巧 
console.log(3 & 1); // 1,位与判断计数的技巧 
console.log(3 | 1); // 3
console.log(3 ^ 1); // 2
console.log(~3); // -4 // 按位全部取反位反码,需要转为原码
console.log(3 >> 1); // 1 
console.log(3 << 1); // 6
console.log(~-3); // 2
console.log(-3 >> 1) // -2

三元运算符

语法:条件表达式?条件为真返回值:条件为假返回值

// 位运算,符号和python一样
// 类似于python的三元表达式,但是语法不同且及其精简
let a = 100;
console.log((a === 100?'true':'false')); // true
console.log(a === 1?'true':'false'); // false

// 等价简单的if...else语句
if (a ===100){
    console.log('true')
}
else{
    console.log('false')
};

逗号操作符

js中,表达式的值指只要是表达式就一定有指向的对象,引用此表达式,就会返回其对应的值;此处存疑

// , 一个运算符,比赋值语句优先级还低
// 类c风格,使用逗号分割的表达式,称为逗号表达式
// 逗号表达式的值等于的其最后一个表达式的值
let a = 4+5, b = true, c = a>20?'true':'false'
console.log(a)
console.log(c)

function test(){
    return 3,a + b,c = a++
}

console.log(test())
console.log(a)
console.log(c)

类型判断

// 类型判断
// instanceof要求必须明确使用类型定义变量,即对象必须是new关键字创建的
// 用于继承关系的判断
console.log('a' instanceof String); // false
console.log(1 instanceof Number); // false

let a = new String('b'); // js中,构建类实例的语法:new 类()
console.log(a instanceof String);
console.log(new Number(1) instanceof Number);

// type
console.log(typeof 'a'); // string
console.log(typeof 1); // number
console.log(typeof a); // object

delete

  • delete关键字,删除一个对象 / 一个对象的属性 / 一个数组中某一个键值
// delete删除对象、属性、数组元素
// 变量
x = 42;
var y = 43;
let z = 60;
obj = new Number();
obj.h = 4
console.log(delete x); // true(can delete if declared implicitly)
console.log(delete y); // 严格定义(cannot delete if declared with var)
console.log(delete z); // 严格定义,不能delete,返回false

// 对象、对象属性
console.log(delete Math.PI); // false,内建类行,可以delete
console.log(delete obj.h); // true,用户定义的类属性,可以delete
console.log(delete myobj); // true,用户定义的类,可以delete

// 数组元素
var trees = new Array('redwood','bay','cedar','oak','maple');
for (var i=0;i<trees.length;i++){
    console.log(trees[i])
};

console.log('==='.repeat(10));
delete trees[3]; // 元组中元素被delete,不会从数组中移出,而是将空的位置变为undefined
for (var i=0;i<trees.length;i++){
    console.log(trees[i])
};

console.log(trees); // 空着的位置显示为<1 empty item>
console.log(trees[3]); // 直接访访问为undefined

in,判断属性是否在对象内

python中的关键in是判断值是否在对象内,注意两者的区别

var trees = new Array('redwood','bay','cedar','oak','maple');
console.log(0 in trees); // true,0在tree的index中
console.log(3 in trees); // true,3在tree的index中
console.log(5 in trees); // false,5不在tree的index中
console.log('length' in trees); // length,是数组对象的属性
console.log('bay' in trees); // 'bay'是数组对象的值,in关键字判断的是对象属性

delete trees[3];
for (var i=0;i<trees.length;i++){
    console.log(trees[i])
};
console.log(3 in trees); // 注意,虽然可以遍历,但是3已经不在trees属性中
console.log('==='.repeat(10));

let mycar = {
    color:"red",
    year:1998
};

console.log('color' in mycar); // true
console.log('model' in mycar); // false
console.log('year' in mycar); // true

运算符优先级

  • 单目运算符 > 双目运算符 > 三目运算符 > 赋值语句 > 逗号
    • js中,逗号运算符的优先级最低
  • 三目运算符,由 ?: 组成,此处存疑

表达式

  • 基本表达式,和Python差不多
  • 解析式也和Python差不多,但在ES6中非标准,不推荐使用
  • ES6开始支持,推荐使用生成器函数

块作用域

函数块作用域

函数块作用域中,严格定义的变量对外不可见;隐式定义的变量对外不可见。请使用严格定义

// 块作用域,简单的说,一个大括号就是一个块作用域
// let定义一个块作用域变量
function hello(){
    let a = 1;
    var b = 2;
    c = 3;
    const D = 100;
};

// console.log(a) // 函数块作用域中,let定义的变量对外不可见
// console.log(b) // 函数块作用域中,var定义的变量对外不可见
console.log(D) // 函数块作用域中,const定义的变量对外不可见
console.log(c) // 函数作用域中,隐式定义的变量相当于全局变量,对外可见,及其危险

var j = 8

function test(){
    var j = 10 // 函数块作用域中,var不会将变量声明至全局,即全局变量
}

test()
console.log(j)

if、while、for语句块作用域

  • if、while、for嵌套语句中,虽然生成了块作用域,但是没有闭包的概念
    • let、const严格定义的常量,在if、while、for的作用域中对外不可见
    • var、隐式定义的常量,在if、while、for的作用域中对外可见

闭包只的是在嵌套函数中,内层函数使用了外层函数的自由变量,注意区别

if (1){
    let d = 4;
    var e = 5;
    f = 6
    const h = 10
    if (true){
        console.log(d) // 4
        console.log(e) // 5
        console.log(f) // 6
        console.log(h) // undefiend
        console.log('---'.repeat(30))
        g = 10
        var j; // var会将变量声明至全局,即在此语句前访问j,返回undefiend;
        // 函数块作用域中,var不会将变量声明至全局,类块作用中暂时未知
        j = 7
    }
};

// console.log(d) // if、while、for循环作用域中,let严格定义的变量,对外不可见
// console.log(h) // if、while、for循环作用域中,const严格定义的常量,对外不可见
console.log(e); // var严格定义的变量,对外可见
console.log(f); // 隐式定义的变量,对外可见

流程控制

条件分支

if…else if … else

  • 条件判断中,等效fasle的类型:false、undefined、null、0、NaN、空字符串

    • 其他值均等效true,**注意:{}、[]等效true
  • 语法

if (condition1)/* 注意:if语句的条件必须写在小括号内 */
{
    expression1
}
else if (condition2) // 注意:一个分支,一个大括号
{
    expression2
}
else if (condition3) // 注意: js中,分支关键字是else if
{
    expression3
}
else
{
    expression4
};
  • 测试代码
let i = 'a';

if (typeof i === 'string')/* 注意:if语句的条件必须写在小括号内 */
{
    console.log(`${i} is string`)
}
else if (i < 8) // 注意:一个分支,一个大括号
{
    console.log(`${i} < 8`)
}
else if (i > 8) // 注意: js中,分支关键字是else if
{
    console.log(`${i} > 8`)
}
else
{
    console.log(`${i} === 8`)
};

swith…case…default

该语法存疑

  • 语法
switch (expression){ // 注意,case语句都在一个大括号内
    case label_1: 
        statements_1
        [break;] 
    case label_2:
        statements_2
        [break;] 
    case 3: 
        statements_3
        [break;] 
    default:
        statements_def
        [break;] 
};
  • 举例
let i = 3;

switch (i){ // 注意,case语句都在一个大括号内
    case 0: // case 0 等价 if i === 0:
        console.log('zero')
        break // break关键字,在switch...case语句中,阻止穿透
    case 1:
        console.log('one')
    case 2:
        console.log('two')
    case 3: // 满足条件,进入分支;注意:之后的分支不用判断,直接穿透进入
        console.log('three') 
        // break // 有break,返回three;否则返回three four
    case 4:
        console.log('four')
    default: // 其他什么都不做
};

循环

for循环

  • 语法
  • for循环执行过程:
    1. 执行initialExpression,且进行condition判断;
    2. 执行statement中的语句;
    3. 最后再执行incrementExpression.
    4. 以此循环
for ([initialExpression];[condition];[incrementExpression])
{
    statement;
};
  • 举例 – 执行步骤
    1. 循环第一步引用变量i进行条件判断(注意,先不用管++、–在i的左边还是右边)
    2. 对变量i进行相关操作
    3. 进行++、–;
    4. 以此循环;
// java风格for循环
for (let i=0;i<5;++i){
    console.log(i);
};

console.log('---'.repeat(10));

// C风格for循环
for (var x=0,y=9;x<5; x++,y--)
{
    console.log(x * y);
};

console.log('---'.repeat(10));

for (let i=0;i<10;i+=3){
    console.log(i);
};

for…in循环

  • 语法
// 对象操作语句for...in,用来迭代遍历对象的属性
for (variable in object) {
    statement;
// }
  • 数组

1.使用for循环,构建索引循环遍历;2.使用for…in循环遍历

let arr = new Array(10,20,30,40); // 等同 arr = [10,20,30,40]

console.log(arr[1]); // 20

for (let x in arr) // js中,只有一条statement,可不用大括号,但是建议这样做
    console.log(x); // 返回索引属性;注意,arr还有length属性

for (let index in arr){
    console.log(`${index} : ${arr[index]}`);
};
  • 对象

注意:对象只能使用for…in循环,迭代遍历属性

let obj={
    a:1, // 注意,js中key不为字符串,会将a转为字符串
    b:'js',
    'c':true
};

console.log(obj.a);
console.log(obj['b']); // 对象属性当索引访问
console.log(obj.d); // undefined

for (attr in obj){
    console.log(`${attr} : ${obj.attr}; ---`); // undefined,不能这样使用
    console.log(`${attr} : ${obj[attr]}; +++`);// 返回属性的对象
};

for…of循环

  • ES6新增语法

注意:for…of不能迭代一个普通对象,因为of语句后面必须是iterable;可类比python的for…in iterable循环

for (variable of object){
    statement
};
  • 举例
let arr = [1,2,3,4,5];
let obj = {
    a:1,
    b:arr,
    arr,
};

for (let i of arr){ // 返回数组的元素
    console.log(i);
};

for (let key of obj){ // 抛异常,TypeError: obj is not iterable
    console.log(key);
};

for循环的差别

let arr = [1,2,3,4,5];
let obj = {
    a:1,
    b:arr,
    arr,
};

function test1(arr){
    for (let x in arr){ // 遍历数组index属性或对象属性
        console.log(x,typeof x,arr[x]);
    };
    for (let x of arr){ // 遍历数组元素,注意不能遍历对象
        console.log(x,typeof x);
    };
    for (let x=0;x<5;x++){ // 自定义索引数值进行遍历,注意不能遍历对象
        console.log(x,arr[x]);
    };
};

test1(arr)

function test2(arr){
    for (let x in arr){ // 遍历数组index属性或对象属性
        console.log(x,typeof x,arr[x]);
    };

    if (typeof arr !== 'object'){
        for (let x of arr){ // 遍历数组元素,注意不能遍历对象
            console.log(x,typeof x);
        };
    };
    if (typeof arr != 'object'){
        for (let x=0;x<5;x++){ // 自定义索引数值进行遍历,注意不能遍历对象
            console.log(x,arr[x]);
        };
    };  
};
test2(obj)

while循环

  • 语法
  • 执行顺序
    1. condition进行条件判断
    2. condition中如果有表达式,执行表达式
    3. 执行statement中的语句
    4. 以此循环
while (condition){
    statement
};
  • 举例
    let i = 10
// 注意:执行循序
// 1. i进行条件判断;
// 2. 满足,进行--操作;
// 3. 引用变量i
while (i--){ 
    console.log(i)
};

do…while循环

  • 语法
  • 执行顺序
    1. 执行do语句中的statement
    2. 判断conditon
    3. condtion如果有表达式,执行
    4. 以此循环
do 
    statement
while (conditon)
  • 举例
let x = 3;

for (x;x>=0;x--){
    console.log(x) // 先引用x,后执行--
}

console.log('---'.repeat(10))

do {
    console.log(x); // 先执行,后判断
} 
while /* 先判断,后++ */ (x++<3); 
  • 返回值
3
2
1
0
------------------------------
-1
0
1
2
3
4

break、continue

  • break 结束当前循环,使用原则同python
    • 注意:js的swtich…case分支语句中的break,为阻止穿透
  • continue 中断当前循环,跳过直接进入下一次循环,使用原则同python

果有表达式,执行表达式
1. 执行statement中的语句
1. 以此循环

while (condition){
    statement
};
  • 举例
    let i = 10
// 注意:执行循序
// 1. i进行条件判断;
// 2. 满足,进行--操作;
// 3. 引用变量i
while (i--){ 
    console.log(i)
};
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值