一、 JS三种书写位置
- 行内式
<input type="button" value="点击了按钮" onclick="alert('我是行内js')">
<!-- html中使用双引号,js中使用单引号 -->
html中使用双引号,js中使用单引号
- 内嵌式
<script>
alert('我是内嵌式js');
alert('我是内嵌式js')
</script>
- 外部引用
<script src="my.js"></script>
<!-- 两个标签中间不可以再写代码了 -->
要注意!!两个标签中间不可以再写代码了
二、 声明变量、输入输出、数据类型
1.基本使用
//1.声明年龄age变量
var age;
//2.prompt读取用户输入
age = prompt('请输入年龄',18);
//3.alert输出
alert('年龄是'+age);
//4.console.log控制台输出
console.log(age);
2.同时声明多个变量
var age = 18,
address = 'guangzhou',
phone = 13700;
3.数据类型
- js的数据类型有:
数据类型 | 默认值 |
---|---|
Number | 0 |
Boolean | false |
String | ’ ’ |
Undefined | underfined |
Null | null |
Object(包括array、function、date等等) | null |
Symbol(ES6) | symbol |
- js变量数据类型可变(弱类型)
var num = 12; num = 'red';
- js字符串长度与拼接
var str1 = 'abbbss';
var str2 = 'ccdd';
console.log('str1的长度为:'+str1.length); //强制类型转换 str1的长度为:6
console.log(str1+str2); //abbbssccdd
console.log(true + 'abc'); //trueabc js字符最大
console.log(undefined + 'abc'); //undefinedabc js字符最大
console.log(null + 'abc'); //nullabc js字符最大
console.log(true + 1); //2
console.log(undefined + 1); //NaN
console.log(null + 1); //1 null和undefined的区别
- typeof 检测数据类型
console.log(typeof('abc')); //string
console.log(typeof(abc)); //undefined
console.log(typeof(NaN)); //number
console.log(typeof(null)); //object
- js数据类型转换
//转string
var num = 1;
//1.
alert(num.toString());
//2.
alert(String(num));
//3.
alert(String(num+''));
//转number
var str = '12.34px' ;
//1.
alert(parseInt(str)); //12
//2.
alert(parseFloat(str)); //12.34
//3.
alert(str - 0); //- * /隐式转换 12.34
//4.
alert(Number(str)); //12.34
//转boolean
//0、NaN、null、undefined 都是false 其余都是true
alert(Boolean(0)); //false
- symbol特点
-
symbol(1) === symbol(1) // false
每个symbol的值都是唯一的(存在内存中我们不知道),不受其括号中备注的影响 -
创建symbol的时候不能
new
,symbol看起来像函数,但实际上只是基础类型let s = Symbol(123)
-
symbol 不能隐式转换为任何其他类型,但是可以显式转换为除了数字以外的任何类型
-
let s = Symbol(123)
console.log(String(s)) // Symbol(123)
console.log(Number(s)) // 报错
- symbol常用于
- 创建很多个常量,并且能保证每个常量不重复
- 定义对象的唯一属性名 不会被
obeject.key
和for in
和JSON.stringify()
遍历到,保护个别隐私(例如定义对象的密码为symbol属性[Symbol('password')]:'123456'
)
let s = Symbol()
let obj = {
[s]: 'hello' //要加中括号,否则会被识别为常规的字符串键名
}
console.log(obj) // { [Symbol()]: 'hello' }
console.log(obj[s]) // hello
三、运算符与运算
1.js浮点数运算
alert(0.1+0.2) //0.0.30000000000000004 js浮点数不能直接相比较
//
var num = (0.1*10 + 0.2*10) / 10
alert(num) //0.3
alert(num == 0.3) //true
2.===
与==
的区别
===
要求变量类型和值都相等,==
仅仅要求值相等(==会将字符数据转换为数字型)
console.log(12 == '12') //true
console.log(12 === '12') //false
3.逻辑中断(短路运算)
- 如果’&&'前面的表达式为真,则返回第二个表达式
- 如果’&&'前面的表达式为假,则返回第一个表达式,剩下的不执行
console.log(123 && 12) //12
console.log(0 && 12) //0
- '||'找表达式中第一个为真的值返回,剩下的不执行
四、流程控制
1.switch
let arguments = process.argv.slice(2);
let name = arguments[0]
switch (name){
case '李华':
console.log('李华成绩为90')
break
case '张三':
console.log('张三成绩为95')
break
}
2.for
- 输出乘法表
for (let i = 1; i <= 9; i++) {
let str = ''
for (let j = 1; j <= i; j++) {
str = str + j + '×' + i + '=' + i * j + ' '
}
console.log(str + '\n')
}
五、数组
1. 数组创建
- new创建数组
let arr1 = new Array() // 创建了一个空数组
- 创建空数组
let arr2 = [] // 创建了一个空数组
- 利用数组字面量创建数组
let arr3 = [1, 'abc', true] // 一个数组可以存放多类型数据
2.遍历数组
for
循环遍历
let arr = [1, 'abc', true]
for (let i = 0; i < arr.length; i++) {
console.log( arr[i])
}
forEach
遍历(直接使用element
不能修改元素值,要使用下标形式array[index]
)
let arr = [1, 'abc', true]
arr.forEach( (element,index,arr) => {
console.log('第' + index + '个元素为: ',element)
console.log('数组本身为: ' ,arr)
});
for in
遍历(通常用于对象)
let obj = {
name: '李华',
score: 95,
}
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
console.log('属性' + key + '为: ' , obj[key])
}
}
for of
遍历(不能用于对象,而且遍历的是集合的值)
let arr = [1, 'abc', true]
for (const value of arr) {
console.log(value)
}
for in
和for of
区别- for in是ES5标准,遍历
key
,for of是ES6标准,遍历value
- for in 会遍历
原型链
来输出关联的所有属性,但是 for of 不会(同时也不会遍历没有迭代器对象的集合,例如普通对象就没有迭代器)
- for in是ES5标准,遍历
3.数组常用操作方法
concat()
连接数组(不改变原数组,返回一个新数组)
let arr1 = [1, 'abc', true]
let arr2 = [1, 'abc', true]
let arr3 = arr1.concat(arr2)
console.log(arr3) // [ 1, 'abc', true, 1, 'abc', true ]
join()
join() 方法用于把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分隔的,默认使用’,'号分割,不改变原数组。
let arr1 = [1, 'abc', true]
let arr2 = arr1.join()
console.log(typeof arr1) // object
console.log(typeof arr2) // string
push()
和pop
push() 方法可向数组的末尾添加一个(可以多个),并返回新的长度。而pop()删除并返回数组的最后一个元素
let arr1 = [1, 'abc', true]
let len = arr1.push(2,3)element
console.log(arr1,len) // [ 1, 'abc', true, 2, 3 ] 5
element = arr1.pop()
console.log(arr1,element) // [ 1, 'abc', true, 2 ] 3
shift()
和unshift
shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。unshift则向开头添加新元素,返回新长度
let arr1 = [1, 'abc', true]
let element = arr1.shift()
console.log(arr1,element) // [ 'abc', true, ] 1
len = arr1.unshift(123)
console.log(arr1,len) // [ 123, 'abc', true] 3
slice()
返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素
字符串也可以直接用slice
在做截取的时候推荐使用slice
let arr1 = [1, 2, 3, 4, 5]
let arr2 = arr1.slice(1,2)
let arr3 = arr1.slice(1,3)
console.log(arr2,arr3) // [ 2 ] [ 2, 3 ]
let arr4 = arr1.slice(0,-2) //还支持负数截取
console.log(arr4) // [ 1, 2, 3 ]
let str = '123456'
let str1 = str.slice(0,-2) //还支持截字符串
console.log(str1) // 1234
splice()
splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。如果从删除了元素,则返回的是含有被删除的元素的数组。splice() 方法会直接对数组进行修改。
let arr1 = [1, 2, 3, 4, 5]
let arr2 = arr1.splice(1,2,666) // 删除序号为1开始的后2个元素,即arr1[1],arr1[2] 并返回这两个元素
console.log(arr1,arr2) // [ 1, 666, 4, 5 ] [ 2, 3 ]
let arr3 = arr1.splice(1,0,777) // 不删除则直接在该位置插入元素
console.log(arr1,arr3) // [ 1, 777, 666, 4, 5 ] []
substring()
和substr()
在单参数时都表示该位置元素和后面元素组成的字符串
在两个参数时有所不同:
substr(start,length),第一个参数是起始的index,后面的是要截取的长度
substring(start,to),第一个参数是起始的index,后面的是截到的index
注意:substr
没有进入ECMA标准,将来会被弃用 ,以后无脑使用slice
来分割字符串就好啦
let str = '12345678'
console.log(str.substr(2,5)) // 34567 第二个参数表示长度
console.log(str.substring(2,5)) // 345 第二个参数表示下标
sort
排序
按照 Unicode code 位置排序,默认升序,
arrayObject.sort(sortby);参数sortby可选。规定排序顺序。必须是函数,所以一定要写排序函数
let arr1 = [1, 200, 45, 10, 5]
console.log(arr1.sort()) // [ 1, 10, 200, 45, 5 ]
console.log(arr1.sort((a, b) => { // [ 1, 5, 10, 45, 200 ]
return a - b
}))
reverse()
reverse() 方法用于颠倒数组中元素的顺序。返回的是颠倒后的数组,会改变原数组
let arr1 = [1, 2, 3, 4, 5]
console.log(arr1.reverse()) // 234
indexOf
和lastIndexOf
顾名思义,根据index查找值
都接受两个参数:查找的值、查找起始位置
不存在,返回 -1 ;存在,返回位置。indexOf 是从前往后查找, lastIndexOf 是从后往前查找。
let arr1 = ['butty', 'marry', 'bob', 'acb', 'dan']
console.log(arr1.indexOf('bob')) // 2
console.log(arr1.indexOf('hello')) // -1 表示没有查找到
every
、some
、filter
some
对数组的每一项都运行给定的函数,任意一项都返回 ture,则返回 true
every
对数组的每一项都运行给定的函数,每一项返回 ture,则返回 true
filter
对数组的每一项都运行给定的函数,返回符合条件的元素组成的数组
let arr1 = [1, 20, 300, 4000, 555]
let ans1 = arr1.some((element) => {
return element > 200
})
console.log(ans1) // true
//---------------------------------
let ans2 = arr1.every((element) => {
return element > 200
})
console.log(ans2) // false
//---------------------------------
let arr2 = arr1.filter((element) => {
return element > 200
})
console.log(arr2) // [ 300, 4000, 555 ]
map
和forEach
map
对数组的每一项都运行给定的函数,返回每次函数调用的结果组成一个新数组
let arr1 = [1, 20, 300, 4000, 555]
let arr2 = arr1.map((element) => {
return element * 200
})
console.log(arr2) // [ 200, 4000, 60000, 800000, 111000 ]
和foreach区别:
- forEach() 方法不会返回执行结果,而是undefined。
- forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
- forEach() 的执行速度 < map() 的执行速度
六、函 数
1.Aruguments
的使用
- arugments是伪数组,不是真正意义上的数组
- 使用索引方式进行存储
- 没有真正数组的
pop() push()
方法
function fun(){
console.log(arguments) // [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
console.log(arguments[0]) // 1
}
fun(1,2,3,4)
2.预解析
- 作用域链:当有多个同名变量时,依照就近原则去寻找变量值
- 预解析分为:变量预解析、函数预解析
//未变量提升的源代码
var num = 10
fun()
function fun(){
console.log(num) //输出undefined 具体为什么看下面变量提升
var num = 20
}
//变量提升后
var num // 预解析
function fun(){ // 预解析
var num // 预解析
console.log(num) //输出undefined 根据就近原则 num为undefined
num = 20
}
num = 10
fun()
七. JS异步
-
js没有真异步,js的异步是通过主线程和异步子线程分开按顺序执行来实现的,两者之间有主次,即先执行主线程,再执行异步子线程
-
执行顺序:同步 > 异步 > 回调
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log('i: ',i);
}, 1000);
}
console.log(i);
//输出
5
i: 5
i: 5
i: 5
i: 5
i: 5
-
在上述代码for循环和外部的console是同步的,所以先执行for循环,读到回调的时候,将其加入消息队列堆栈(未被执行),再执行外部的console.log。
-
主线程执行后,最后执行堆栈中的setTimeout回调