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循环执行过程:
- 执行initialExpression,且进行condition判断;
- 执行statement中的语句;
- 最后再执行incrementExpression.
- 以此循环
for ([initialExpression];[condition];[incrementExpression])
{
statement;
};
- 举例 – 执行步骤
- 循环第一步引用变量i进行条件判断(注意,先不用管++、–在i的左边还是右边)
- 对变量i进行相关操作
- 进行++、–;
- 以此循环;
// 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循环
- 语法
- 执行顺序
- condition进行条件判断
- condition中如果有表达式,执行表达式
- 执行statement中的语句
- 以此循环
while (condition){
statement
};
- 举例
let i = 10
// 注意:执行循序
// 1. i进行条件判断;
// 2. 满足,进行--操作;
// 3. 引用变量i
while (i--){
console.log(i)
};
do…while循环
- 语法
- 执行顺序
- 执行do语句中的statement
- 判断conditon
- condtion如果有表达式,执行
- 以此循环
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)
};