黑马程序员前端JavaScript入门到精通全套视频教程,javascript核心进阶ES6语法、API、js高级等基础知识和实战教程
堆栈空间分配区别:
下面介绍两种常见的浏览器垃圾回收算法: 引用计数法和标记清除。
function fn() {
let o1 = {}
let o2 = {}
o1.a = o2
o2.a = o1
return '引用计数无法回收'
}
fn()
function outer() {
let i = 1
fucntion fn() {
console.log(i)
}
return fn
}
const fun = outer()
fun() // 1
// 外层函数使用内部函数的变量
// 简约写法
function outer() {
let i = 1
return fucntion () {
console.log(i)
}
}
const fun = outer()
fun() // 调用fun 1
// 外层函数使用内部函数的变量
let count = 1
function fn() {
count++
console.log('函数被调用${count}次')
}
fn() // 2
fn() // 3
function fn() {
let count = 1
function fun() {
count++
console.log('函数被调用${count}次')
}
return fun
}
const result = fn()
result() // 2
result() // 3
变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问(仅存在于var声明变量)
注意:
JS初学者经常花很多时间才能习惯变量提升,还经常出现一些意想不到的bug,正因为如此,ES6 引入了块级作用域,用 let 或者 const 声明变量,让代码写法更加规范和人性化。
用 var 关键字声明变量会有变量提升
变量提升是什么流程?
我们不建议使用var声明变量
// 调用函数
foo()
// 声明函数
function foo() {
console.log('声明之前即被调用...')
}
// 不存在提升现象
bar() // 错误
var var = function() {
console.log('函数表达式不存在提升现象...')
}
function sum() {
// console.log(arguments)
let s = 0
for(let i = 0; i < arguments.length; i++) {
s += arguments[i]
}
console.log(s)
}
// 调用求和函数
sum(5, 10)
sum(1, 2, 4)
function getSum(...other) {
// other 得到 [1,2,3]
console.log(other)
}
getSum(1, 2, 3)
function config(baseURL, ...other) {
console.log(baseURL) // 得到 http://baidu.com
console.log(other) // 得到 ['get', 'json']
}
config('http://baidu.com', 'get', 'json');
const arr = [1, 5, 3, 8, 2]
console.log(...arr) // 1 5 3 8 2
const arr = [1, 5, 3, 8, 2]
console.log(Math.max(...arr)) // 8
console.log(Math.min(...arr)) // 1
// 合并数组
const arr1 = [1, 2, 3]
const arr2 = [4 ,5, 6]
const arr3 = [...arr1, ...arr3]
console.log(arr3) // [1,2,3,4,5,6]
语法1:基本写法
// 普通函数
const fn = function() {
console.log('我是普通函数')
}
fn()
// 箭头函数
const fn = () => {
console.log('我是箭头函数')
}
fn()
语法2:只有一个参数可以省略小括号
// 普通函数
const fn = function(x) {
return x + x
}
console.log(fn(1)) // 2
// 箭头函数
const fn = x => {
return x + x
}
console.log(fn(1)) // 2
语法3:如果函数体只有一行代码,可以写到一行上,并且无需写 return 直接返回值
// 普通函数
const fn = function(x, y) {
return x + y
}
console.log(fn(1, 2)) // 3
// 箭头函数
const fn = (x, y) => x + y
console.log(fn(1, 2)) // 3
// 更简洁的语法:
const form = document.querySelector('form')
form.addEventListener('click', ev => ev.preventDefault())
语法4:加括号的函数体返回对象字面量表达式
const fn1 = uname => ({uname: uname})
console.log(fn1('pink老师')) // {uname: 'pink老师'}
总结
const getSum = (...arg) => {
let sum = 0
for(let i = 0; i < args.lenth; i++) {
sum += args[i]
}
return sum // 注意函数体有多行代码需要 return
}
console.log(getSum(1, 2, 3)) // 6
console.log(this) // 此处为 window
const sayHi = function() {
console.log(this) // 普通函数指向调用者,此处为 window
}
btn.addEventListener('click', function() {
console.log(this) // 当前 this 指向 btn
})
console.log(this) // 此处为 window
// 箭头函数
const sayHi = () => {
console.log(this) // 箭头函数此处为 window
}
btn.addEventListener('click', () => {
console.log(this) // 当前 this 指向 window
})
const user = {
name: '小明',
// 该箭头函数中的 this 为函数声明环境中 this 一致
walk: () => {
console.log(this) // 指向 window,不是 user
}
}
user.walk()
const user = {
name: '小明',
sleep: function () {
console.log(this) // 指向 user
const fn = () => {
console.log(this) // 指向 user,该箭头函数中的 this 与 sleep 中的 this 一致
}
// 调用箭头函数
fn()
}
}
user.sleep()
const [max, min, avg] = [100, 60, 80]
console.log(max) // 100
console.log(min) // 60
console.log(avg) // 80
// 普通的数组
const arr = [1, 2, 3]
// 批量声明变量 a b c
// 同时将数组单元值 1 2 3 依次赋值给变量 a b c
const [a, b, c] = arr
console.log(a) // 1
console.log(b) // 2
console.log(c) // 3
let a = 1
let b = 3; // 这里必须有分号!!!
[b, a] = [a, b]
console.log(a) // 3
console.log(b) // 1
// 1. 立即执行函数
(function t() {})();
// 或者
;(function t() {})()
// 2. 数组解构
// 数组开头的,特别是前面有语句的一定注意加分号
;[b, a] = [a, b]
const [a, b, c, d] = ['小米', '苹果', '华为']
console.log(a) // 小米
console.log(b) // 苹果
console.log(c) // 华为
console.log(d) // undefined
const [a, b, c] = ['小米', '苹果', '华为', '格力']
console.log(a) // 小米
console.log(b) // 苹果
console.log(c) // 华为
const [a, b, ...tel] = ['小米', '苹果', '华为', '格力', 'vivo']
console.log(a) // 小米
console.log(b) // 苹果
console.log(tel) // ['华为', '格力', 'vivo']
const [a = '手机', b = '华为'] = ['小米']
console.log(a) // 小米
console.log(b) // 华为
const [a, , c, d] = ['小米', '苹果', '华为', '格力']
console.log(a) // 小米
console.log(c) // 华为
console.log(d) // 格力
const [a, b] = ['苹果', ['小米', '华为']]
console.log(a) // 苹果
console.log(b) // ['小米', '华为']
const [a, [b, c]] = ['苹果', ['小米', '华为']]
console.log(a) // 苹果
console.log(b) // 小米
console.log(c) // 华为
// 普通对象
const user = {
name: '小明',
age: 18
};
// 批量声明变量 name age
// 同时将数组单元值 小明 18 依次赋值给变量 name age
const [name, age] = user
console.log(name) // 小明
console.log(age) // 18
// 普通对象
const user = {
name: '小明',
age: 18
};
// 把原来的name变量重新命名为uname
const [name: uname, age] = user
console.log(uname) // 小明
console.log(age) // 18
const pig = [
{
name: '佩奇',
age: 6
}
]
const [{name, age}] = pig
console.log(name, age)
// 依次打印家庭成员
const pig = {
name: '佩奇',
family: {
mother: '猪妈妈',
father: '猪爸爸',
sister: '乔治'
},
age: 6
}
const { name, family: {mother, father, sister} } = pig
console.log(name) // 佩奇
console.log(mother) // 猪妈妈
console.log(father) // 猪爸爸
console.log(sister) // 乔治
// 这是后台传递过来的数据,请选出data里面的数据方便后面渲染
const msg = {
"code": 200,
"msg": "获取新闻列表成功",
"data": [
{
"id": 1,
"title": "xxx",
"count": 58
},
{
"id": 2,
"title": "yyy",
"count": 56
},
{
"id": 3,
"title": "zzz",
"count": 1800
}
]
}
const {data} = msg
console.log(data)
// 将上面对象只选出data数据,传递给另外一个函数
function render({ data }) {
// 内部处理
console.log(data)
}
render(msg)
// 为了防止msg里面的data名字混淆,渲染函数里面的数据名改为 myData
function render({ data: myData }) {
// 内部处理
console.log(myData)
}
render(msg)
被遍历的数组.forEach(function (当前数组元素, 当前元素索引号) {
// 函数体
})
const arr = ['pink', 'red', 'green']
arr.forEach(function (item, index) {
console.log('当前数组元素是:${item}') // 依次打印数组每一个元素
console.log('当前数组元素的索引是:${index}') // 依次打印数组每一个元素的索引
})
被遍历的数组.filter(function (currentValue, index) {
return 筛选条件
})
// 筛选数组中大于30的元素
const score = [10, 50, 3, 40, 33]
const re = score.filter(function (item) {
return ietm > 30
})
console.log(re) // [50, 40, 33]