一、作用域
1、局部作用域
函数作用域
函数内部声明的变量,在函数外部无法被访问;
函数的参数也是函数内部的局部变量;
不同函数内部声明的变量无法互相访问;
函数执行完毕后,函数内部的变量实际被清空了。
块作用域
let
声明的变量会产生块作用域,var
不会产生块作用域;
const
声明的常量也会产生块作用域;
不同代码块之间的变量无法互相访问。
2、全局作用域
<script>
标签和 .js
文件的【最外层】就是所谓的全局作用域
尽可能少的声明全局变量,防止全局变量被污染。
<script>
// 此处是全局
function sayHi() {
// 此处为局部
}
// 此处为全局
</script>
3、作用域链
嵌套关系的作用域串联起来形成了作用域链;
相同作用域链中按着从小到大的规则查找变量;
子作用域能够访问父作用域,父级作用域无法访问子级作用域。
4、闭包 :闭包 = 内层函数 + 外层函数的变量
定义:闭包是一种比较特殊和函数,使用闭包能够访问函数作用域中的变量。
作用:
封闭数据,实现数据私有,外部也可以访问函数内部的变量;
它允许将函数与其所操作的某些数据(环境)关联起来;
闭包可能引起内存泄漏。
<script>
function outer() {
const a = 1
function f() {
console.log(a)
}
f()
}
outer()
</script>
二、函数
1、函数参数
默认值:
声明函数时为形参赋值即为参数的默认值;
如果参数未自定义默认值时,参数的默认值为 undefined
;
调用函数时没有传入对应实参时,参数的默认值被当做实参传入。
动态参数:
arguments
是函数内部内置的伪数组,作用是动态获取函数的实参。
<script>
function getSum() {
//arguments : 动态获取函数参数,只存在函数内部 是伪数组
let sum = 0
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i]
}
console.log(sum);
}
getSum(1, 2, 3, 4, 5, 6)
</script>
剩余参数:
...
是语法符号,置于最末函数形参之前,用于获取多余的实参;
借助 ...
获取的剩余实参,是个真数组。
<Script>
//剩余参数 真数组 写在函数内部
function getSum(a, b, ...arr) {
let sum = 0
console.log(arr);
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
// console.log(sum);
return sum;
}
const result = getSum(25, 8, 9, 5, 7, 6)
console.log(result);
</Script>
箭头函数
箭头函数属于表达式函数,因此不存在函数提升;
箭头函数只有一个参数时可以省略圆括号 ();
箭头函数函数体只有一行代码时可以省略花括号 {}
,并自动做为返回值被返回;
<script>
1、箭头函数 基本语法
const fn = () => {
}
fn()
2、只有一个参数的时候,小括号可以省略
const fn1 = x => {
console.log(x);
}
fn1(1)
3、只有一行参数的时候,大括号可以省略
const fn2 = x => console.log(x);
fn2(1)
</script>
箭头函数的参数只能使用 ...
动态获取实参。
三、解构赋值
1、数组结构
将数组的单元值快速批量赋值给一系列变量的简洁语法。
<script>
const arr = [100, 60, 80]
//两种方式
const [max,min,avg] = arr
const [max, min, avg] = [100, 60, 80]
console.log(max);
</script>
2、对象解构
将对象属性和方法快速批量赋值给一系列变量的简洁语法,支持多维解构赋值。
const pig = { name: '佩奇', age: 6 }
const { name, age } = { name: '佩奇', age: 6 }
console.log(name);
const { name: uname, age } = { name: '佩奇', age: 6 }
console.log(uname);
3、forEach遍历数组
<script>
// forEach 就是遍历 加强版的for循环 适合于遍历数组对象
const arr = ['red', 'green', 'pink']
const result = arr.forEach(function (item, index) {
console.log(item) // 数组元素 red green pink
console.log(index) // 索引号
})
// console.log(result)
</script>
4、filter筛选数组
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
<script>
const arr = [10, 20, 30]
const newArr = arr.filter(item => item >= 20)
console.log(newArr)
</script>
四、创建对象
1、构造函数
如果一个函数使用 new
关键字调用,那么这个函数就是构造函数。
使用 new
关键字调用函数的行为被称为实例化。
//创建构造函数
function Pig(uanme, age) {
//this.属性值
this.uname = uanme
this.age = age
}
//new 关键字调用构造函数 ---> 实例化构造函数
const person = new Pig("haibaio", 21)
console.log(person);
2、实例成员
通过构造函数创建的对象称为实例对象(构造函数内部的this就是实例对象),
实例对象中的属性和方法称为实例成员。
//创建构造函数
function Pig(uanme, age) {
//this.属性值
this.uname = uanme
this.age = age
}
//new 关键字调用构造函数 ---> 实例化构造函数
//("haibaio", 21)即为实例对象
const person = new Pig("haibaio", 21)
console.log(person);
3、静态成员
允许直接为函数动态添加属性或方法,构造函数的属性和方法被称为静态成员。
静态成员指的是添加到构造函数本身的属性和方法;
一般公共特征的属性或方法静态成员设置为静态成员;
静态成员方法中的 this
指向构造函数本身。
4、Object方法
Object.assign
静态方法创建新的对象;
Object.keys
静态方法获取对象中所有属性;
Object.values
表态方法获取对象中所有属性值。
<script>
const arr = { name: "haibiao", age: 22 }
//获取属性名用Object.keys
console.log(Object.keys(arr));
//获取属性值用Object.values
console.log(Object.values(arr));
//对象的拷贝Object.assign
const arr1 = {}
Object.assign(arr1, arr)
console.log(arr1);
Object.assign(arr, { gender: "男" })
console.log(arr);
</script>
5、Array方法
实例方法 forEach
用于遍历数组,替代 for
循环 ;
实例方法 filter
过滤数组单元值,生成新数组;
实例方法 map
迭代原数组,生成新数组;
实例方法 join
数组元素拼接为字符串,返回字符串;
实例方法 find
查找元素, 返回符合测试条件的第一个数组元素值,如果没有符合条件的则返回 undefined;
实例方法every
检测数组所有元素是否都符合指定条件,如果所有元素都通过检测返回 true,否则返回 false。
6、包装类
之String
实例属性 length
用来获取字符串的度长
实例方法 split('分隔符')
用来将字符串拆分成数组
实例方法 substring(需要截取的第一个字符的索引[,结束的索引号])
用于字符串截取
实例方法 startsWith(检测字符串[, 检测位置索引号])
检测是否以某字符开头
实例方法 includes(搜索的字符串[, 检测位置索引号])
判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false
实例方法 toUpperCase
用于将字母转换成大写
实例方法 toLowerCase
用于将就转换成小写
实例方法 indexOf
检测是否包含某字符
实例方法 endsWith
检测是否以某字符结尾
实例方法 replace
用于替换字符串,支持正则匹配
实例方法 match
用于查找字符串,支持正则匹配
注:String 也可以当做普通函数使用,这时它的作用是强制转换成字符串数据类型。
之Number
<script>
// 使用构造函数创建数值
let num1 = new Number('10')
let num2 = new Number(5)
// 字面量创建数值
let a = 20
</script>
实例方法 toFixed
用于设置保留小数位的长度。
五、面向对象
三大特性
封装性、继承性、多态性。
六、原型对象
1、特性
每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象;
这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存;
把那些不变的方法,直接定义在 prototype 对象上,所有对象的实例就可以共享这些方法;
构造函数和原型对象中的this 都指向 实例化的对象。
<script>
function Person() {
// 此处未定义任何方法
}
// 为构造函数的原型对象添加方法
Person.prototype.sayHi = function () {
console.log('hello');
}
// 实例化
let p = new Person();
p.sayHi(); // 输出结果为 hello
</script>
2、工作机制
当访问对象的属性或方法时,先在当前实例对象是查找,然后再去原型对象查找,并且原型对象被所有实例共享。
3、constructor 属性
每个原型对象里面都有个constructor 属性(constructor 构造函数)
作用:该属性指向该原型对象的构造函数
4、对象原型
对象都会有一个属性 proto 指向构造函数的 prototype 原型对象;
proto用来表明当前实例对象指向哪个原型对象prototype;
proto对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数。
5、原型继承
<script>
const person = {
eyes: 2,
head: 1
}
//通过原型继承 person
Man.prototype = person
//指回原来的构造方法
Man.prototype.constructor = Man
function Man() {
}
const phb = new Man()
console.log(phb);
</script>
6、原型链
① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
② 如果没有就查找它的原型(也就是 proto指向的 prototype 原型对象)
③ 如果还没有就查找原型对象的原型(Object的原型对象)
④ 依此类推一直找到 Object 为止(null)
⑤ proto对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线
⑥ 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上