一、ES5
1.JSON
-
json
是一种特殊的字符串格式,在各种语言中都识别 -
当需要传递数据的时候可以把数据转成json字符串格式再进行传递
-
格式类似数组和对象,但是他是一个字符串
-
凡是字符串使用双引号
-
对象和数组里面的值可以是数值类型,字符串,对象,布尔,null,undefined,数组
var jsonObj = '{ "name": "Jack", "age": 18, "gender": "男" }' var jsonArr = '[{ "name": "Jack", "age": 18, "gender": "男" }, { "name": "Jack", "age": 18, "gender": "男" }, { "name": "Jack", "age": 18, "gender": "男" }]'
JSON.stringify
转json字符串
-
JSON.stringify(js对象或数组)
是将 js里面的对象和数组格式转换为 json字符串var jsonObj = JSON.stringify(obj) var jsonArr = JSON.stringify(arr) console.log(jsonObj) console.log(jsonArr)
jsonObj
就是 json 格式的对象字符串jsonArr
就是 json 格式的数组字符串
JSON.parse
转js对象或数组
-
JSON.parse
是将 json 格式的字符串转换为 js 的对象或者数组var jsonObj = '{ "name": "Jack", "age": 18, "gender": "男" }' var jsonArr = '[{ "name": "Jack", "age": 18, "gender": "男" }, { "name": "Jack", "age": 18, "gender": "男" }, { "name": "Jack", "age": 18, "gender": "男" }]' var obj = JSON.parse(jsonStr) var arr = JSON.parse(jsonArr) console.log(obj) console.log(arr)
obj
就是我们 js 的对象arr
就是我们 js 的数组
2.this 关键字
-
每一个函数内部都有一个关键字是
this
-
可以让我们直接使用的
-
重点: 函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系
-
函数内部的 this 指向谁,取决于函数的调用方式
-
全局定义的函数直接调用,
this => window
function fn() { console.log(this) } fn() // 此时 this 指向 window
-
对象内部的方法调用,
this => 调用者
var obj = { fn: function () { console.log(this) } } obj.fn() // 此时 this 指向 obj
-
定时器的处理函数,
this => window
setTimeout(function () { console.log(this) }, 0) // 此时定时器处理函数里面的 this 指向 window
-
事件处理函数,
this => 事件源
div.onclick = function () { console.log(this) } // 当你点击 div 的时候,this 指向 div
-
自调用函数,
this => window
(function () { console.log(this) })() // 此时 this 指向 window
-
3.改变this指向
- 强行改变 this 指向的方法
3.1 call 依次传递参数
-
call
方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向 -
语法:
函数名.call(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...)
var obj = { name: 'Jack' } function fn(a, b) { console.log(this) console.log(a) console.log(b) } fn(1, 2) fn.call(obj, 1, 2)
fn()
的时候,函数内部的 this 指向 windowfn.call(obj, 1, 2)
的时候,函数内部的 this 就指向了 obj 这个对象- 使用 call 方法的时候
- 会立即执行函数
- 第一个参数是你要改变的函数内部的 this 指向
- 第二个参数开始,依次是向函数传递参数
3.2 apply 数组依次传递参数
-
apply
方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向 -
语法:
函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...])
var obj = { name: 'Jack' } function fn(a, b) { console.log(this) console.log(a) console.log(b) } fn(1, 2) fn.call(obj, [1, 2])
fn()
的时候,函数内部的 this 指向 windowfn.apply(obj, [1, 2])
的时候,函数内部的 this 就指向了 obj 这个对象- 使用 apply 方法的时候
- 会立即执行函数
- 第一个参数是你要改变的函数内部的 this 指向
- 第二个参数是一个 数组,数组里面的每一项依次是向函数传递的参数
3.3 bind 生成新指向函数
-
bind
方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向 -
和 call / apply 有一些不一样,就是不会立即执行函数,而是返回一个已经改变了 this 指向的函数
-
语法:
var newFn = 函数名.bind(要改变的 this 指向); newFn(传递参数)
var obj = { name: 'Jack' } function fn(a, b) { console.log(this) console.log(a) console.log(b) } fn(1, 2) var newFn = fn.bind(obj) newFn(1, 2)
- bind 调用的时候,不会执行 fn 这个函数,而是返回一个新的函数
- 这个新的函数就是一个改变了 this 指向以后的 fn 函数
fn(1, 2)
的时候 this 指向 windownewFn(1, 2)
的时候执行的是一个和 fn 一摸一样的函数,只不过里面的 this 指向改成了 obj
二、ES6
1.let 和 const 关键字
-
我们以前都是使用
var
关键字来声明变量的 -
在 ES6 的时候,多了两个关键字
let
和const
,也是用来声明变量的 -
只不过和 var 有一些区别
-
let
和const
不允许重复声明变量// 使用 var 的时候重复声明变量是没问题的,只不过就是后面会把前面覆盖掉 var num = 100 var num = 200
// 使用 let 重复声明变量的时候就会报错了 let num = 100 let num = 200 // 这里就会报错了
// 使用 const 重复声明变量的时候就会报错 const num = 100 const num = 200 // 这里就会报错了
-
let
和const
声明的变量不会在预解析的时候解析(也就是没有变量提升)// 因为预解析(变量提升)的原因,在前面是有这个变量的,只不过没有赋值 console.log(num) // undefined var num = 100
// 因为 let 不会进行预解析(变量提升),所以直接报错了 console.log(num) // undefined let num = 100
// 因为 const 不会进行预解析(变量提升),所以直接报错了 console.log(num) // undefined const num = 100
-
let
和const
声明的变量会被所有代码块限制作用范围// var 声明的变量只有函数能限制其作用域,其他的不能限制 if (true) { var num = 100 } console.log(num) // 100
// let 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...) if (true) { let num = 100 console.log(num) // 100 } console.log(num) // 报错
// const 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...) if (true) { const num = 100 console.log(num) // 100 } console.log(num) // 报错
-
-
let
和const
的区别-
let
声明的变量的值可以改变,const
声明的变量的值不可以改变let num = 100 num = 200 console.log(num) // 200
const num = 100 num = 200 // 这里就会报错了,因为 const 声明的变量值不可以改变(我们也叫做常量)
-
let
声明的时候可以不赋值,const
声明的时候必须赋值let num num = 100 console.log(num) // 100
const num // 这里就会报错了,因为 const 声明的时候必须赋值
-
2.( ) => { } 箭头函数
-
箭头函数是 ES6 里面一个简写函数的语法方式
-
重点: 箭头函数只能简写赋值式函数表达式,不能简写声明式函数
function fn() {} // 不能简写 const fun = function () {} // 可以简写 const obj = { fn: function () {} // 可以简写 }
-
语法:
(函数的行参) => { 函数体内要执行的代码 }
const fn = function (a, b) { console.log(a) console.log(b) } // 可以使用箭头函数写成 const fun = (a, b) => { console.log(a) console.log(b) }
const obj = { fn: function (a, b) { console.log(a) console.log(b) } } // 可以使用箭头函数写成 const obj2 = { fn: (a, b) => { console.log(a) console.log(b) } }
箭头函数的特殊性
-
箭头函数内部没有 this,箭头函数的 this 是上下文的 this
// 在箭头函数定义的位置往上数,这一行是可以打印出 this 的 // 因为这里的 this 是 window // 所以箭头函数内部的 this 就是 window const obj = { fn: function () { console.log(this) }, // 这个位置是箭头函数的上一行,但是不能打印出 this fun: () => { // 箭头函数内部的 this 是书写箭头函数的上一行一个可以打印出 this 的位置 console.log(this) } } obj.fn() obj.fun()
- 按照我们之前的 this 指向来判断,两个都应该指向 obj
- 但是 fun 因为是箭头函数,所以 this 不指向 obj,而是指向 fun 的外层,就是 window
-
箭头函数内部没有
arguments
这个参数集合const obj = { fn: function () { console.log(arguments) }, fun: () => { console.log(arguments) } } obj.fn(1, 2, 3) // 会打印一个伪数组 [1, 2, 3] obj.fun(1, 2, 3) // 会直接报错
-
函数的行参只有一个的时候可以不写
()
其余情况必须写const obj = { fn: () => { console.log('没有参数,必须写小括号') }, fn2: a => { console.log('一个行参,可以不写小括号') }, fn3: (a, b) => { console.log('两个或两个以上参数,必须写小括号') } }
-
函数体只有一行代码的时候,可以不写
{}
,并且会自动 returnconst obj = { fn: a => { return a + 10 }, fun: a => a + 10 } console.log(fn(10)) // 20 console.log(fun(10)) // 20
3.函数参数默认值
-
我们在定义函数的时候,有的时候需要一个默认值出现
-
就是当我不传递参数的时候,使用默认值,传递参数了就使用传递的参数
function fn(a) { a = a || 10 console.log(a) } fn() // 不传递参数的时候,函数内部的 a 就是 10 fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
- 在 ES6 中我们可以直接把默认值写在函数的行参位置
function fn(a = 10) { console.log(a) } fn() // 不传递参数的时候,函数内部的 a 就是 10 fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
- 这个默认值的方式箭头函数也可以使用
const fn = (a = 10) => { console.log(a) } fn() // 不传递参数的时候,函数内部的 a 就是 10 fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
- 注意: 箭头函数如果你需要使用默认值的话,那么一个参数的时候也需要写 ()
4.解构赋值
- 解构赋值,就是快速的从对象或者数组中取出成员的一个语法方式
4.1 { , , , }=解构对象
-
快速的从对象中获取成员
// ES5 的方法向得到对象中的成员 const obj = { name: 'Jack', age: 18, gender: '男' } let name = obj.name let age = obj.age let gender = obj.gender
// 解构赋值的方式从对象中获取成员 const obj = { name: 'Jack', age: 18, gender: '男' } // 前面的 {} 表示我要从 obj 这个对象中获取成员了 // name age gender 都得是 obj 中有的成员 // obj 必须是一个对象 let { name, age, gender } = obj
4.2 [ , , , ]=解构数组
-
快速的从数组中获取成员
// ES5 的方式从数组中获取成员 const arr = ['Jack', 'Rose', 'Tom'] let a = arr[0] let b = arr[1] let c = arr[2]
// 使用解构赋值的方式从数组中获取成员 const arr = ['Jack', 'Rose', 'Tom'] // 前面的 [] 表示要从 arr 这个数组中获取成员了 // a b c 分别对应这数组中的索引 0 1 2 // arr 必须是一个数组 let [a, b, c] = arr
注意
{}
是专门解构对象使用的[]
是专门解构数组使用的- 不能混用
5.``模版字符串
-
ES5 中我们表示字符串的时候使用
''
或者""
-
在 ES6 中,我们还有一个东西可以表示字符串,就是 ``(反引号)
let str = `hello world` console.log(typeof str) // string
-
和单引号好友双引号的区别
-
反引号可以换行书写
// 这个单引号或者双引号不能换行,换行就会报错了 let str = 'hello world' // 下面这个就报错了 let str2 = 'hello world'
let str = ` hello world ` console.log(str) // 是可以使用的
-
反引号可以直接在字符串里面拼接变量
// ES5 需要字符串拼接变量的时候 let num = 100 let str = 'hello' + num + 'world' + num console.log(str) // hello100world100 // 直接写在字符串里面不好使 let str2 = 'hellonumworldnum' console.log(str2) // hellonumworldnum
// 模版字符串拼接变量 let num = 100 let str = `hello${num}world${num}` console.log(str) // hello100world100
- 在 `` 里面的
${}
就是用来书写变量的位置
- 在 `` 里面的
-
6. … 展开运算符
-
ES6 里面号新添加了一个运算符
...
,叫做展开运算符 -
作用是把数组展开
let arr = [1, 2, 3, 4, 5] console.log(...arr) // 1 2 3 4 5
-
合并数组的时候可以使用
let arr = [1, 2, 3, 4] let arr2 = [...arr, 5] console.log(arr2)
-
也可以合并对象使用
let obj = { name: 'Jack', age: 18 } let obj2 = { ...obj, gender: '男' } console.log(obj2)
-
在函数传递参数的时候也可以使用
let arr = [1, 2, 3] function fn(a, b, c) { console.log(a) console.log(b) console.log(c) } fn(...arr) // 等价于 fn(1, 2, 3)
7.Set类型(类似数组)
- Set对象是值的集合,类似数组
- Set中的元素只会出现一次,即 Set 中的元素是唯一的
- 常用方法
var mySet = new Set(['a','b']);
mySet.size;//返回set中元素的个数
mySet.add('foo')
// 在Set对象尾部添加一个元素
mySet.clear()
// 移除Set对象内的所有元素。
mySet.delete('foo')
// 移除Set中与这个值相等的元素,返回一个布尔值
mySet.has(value)
// 返回一个布尔值,表示该值在Set中存在与否。
8.Map类型(类似对象)
- Map对象保存键值对
- 任何值都可以作为一个键或一个值
- 常用方法
- size:返回Map对象的键/值对的数量。
- clear():移除Map对象的所有键/值对 。
- delete(key):移除键值对。
- get(key):返回键对应的值,如果不存在,则返回undefined。
- has(key):返回一个布尔值,表示Map实例是否包含键对应的值。
- set(key, value):设置Map对象中键的值。返回该Map对象。
let myMap = new Map( [["key1", "value1"], ["key2", "value2"]]);
let keyObj = {};
let keyFunc = function() {};
let keyString = 'a string';
// 添加键
myMap.set(keyString, "和键'a string'关联的值");
myMap.set(keyObj, "和键keyObj关联的值");
myMap.set(keyFunc, "和键keyFunc关联的值");
myMap.size; // 3
// 读取值
myMap.get(keyString); // "和键'a string'关联的值"
myMap.get(keyObj); // "和键keyObj关联的值"
myMap.get(keyFunc); // "和键keyFunc关联的值"
myMap.get('a string'); // "和键'a string'关联的值"
// 因为keyString === 'a string'
myMap.get({}); // undefined, 因为keyObj !== {}
myMap.get(function() {}); // undefined, 因为keyFunc !== function () {}
9.for...of
循环遍历
- 可以遍历array , set , map等数据类型
- 不可以遍历对象(
for...in...
)
const array1 = ['a', 'b', 'c'];
for (const element of array1) {
console.log(element);
}
// a
// b
// c
10.模块化语法
import {rand as aaa} from "./public.js"
<!-- 现在我们使用模块化语法导入js模块(js文件) -->
<!-- 如果要使用模块化语法,设置script的type='module' -->
<!-- 如果要打开这个html文件要以http形式打开 -->
<script type="module">
// 1 导入外部的js文件,导入以后这个js文件会执行一次
// 里面的变量不能使用
// import "./public.js"
// 2 导入外部的js文件,导入以后这个js文件会执行一次
// 然后把js文件中export default的变量赋值给aaa
// import aaa from "./public.js"
// console.log(aaa)
// 3 导入外部的js文件,导入以后这个js文件会执行一次
// 然后把js文件中export的变量赋值给同名的变量
// 如果要重命名要用as
import {rand as aaa} from "./public.js"
console.log(aaa)
</script>