8.3 KiB
8.3 KiB
JavaScript基础
-
js特性:
- js是一门动态语言,包含类型、运算符、标准内置对象和方法
- js支持函数是编程
- js通过原型链来实现面向对象编程
-
js类型
- js中包括如下类型:
- Number:数字
- String:字符串
- Boolean:布尔
- Function:函数
- Object:对象
- Symbol:符号
- 其他类型:
- undefined
- null
- Array
- Date
- RegExp
- js中包括如下类型:
-
js变量的声明
- js可通过如下关键字来声明变量:
- let:
- 块级作用域内有效,只能在声明该变量的块中使用
- 在let声明变量之后,变量只能在声明之后被使用
- const:
- 声明一个不可变的变量,该变量在定义域中总是可见的
- const变量也只能在块定义域中被使用,在声明块之外无法访问
- var:
- 通过var关键字声明变量之后,变量在整个函数的范围内都是可见的
- 在定义var变量的方法之外,均无法访问var变量
- 但是在声明var变量的方法中,即使在声明var变量的语句之前,也可以使用var变量,变量值为undefined
- let:
- js变量作用域特性:
- 在js语言中,原本是没有块作用域的,变量只有函数范围的作用域。但是,通过引入const和let关键字,js支持声明块作用域的变量。
- js可通过如下关键字来声明变量:
-
js运算符
- ==运算符和===运算符
- ==运算符具有类型自适应的功能
# 对于==运算符,如果运算符两边的类型不一致的话, # 会尝试进行类型转换并比较 123==“123” true 1==true true - ===相对于==,比较前并不会进行强制类型转换
1===‘1’ false 1===true false - 相对应的,对于比较不相等的操作,也存在!=和!==操作,其区别类似于==和===的区别
- ==运算符具有类型自适应的功能
- ==运算符和===运算符
-
js流程控制
- js中for循环可以分为如下两种
- for in循环:
- 对于for in循环,会遍历索引项(对数组来说是序号,对map来说是key,set为空)
- for of循环:
- 对于for of循环,会遍历值(value)而不是键(key)
- for in循环:
- js中的switch流:
- 相比于c中的switch只支持数字,js中的switch既支持数字又支持字符串,switch和case之间是通过===运算符来判断是否严格相等的
- js中for循环可以分为如下两种
-
js对象
- js对象类似与map结构,由key和value组成的键值对构成
- js对象的创建有如下两种方式
- 字面量创建
let obj={ name:"touma", id:"A001", husband:{ name:"haruki", id:"A002" } }- 通过对象原型来创建对象
function Person(name,id) { this.name=name this.id=id } let person=new Person("touma","A001") - 访问对象元素的方式
let person={ name:"touma", id:"A001" } // 通过.来访问 cosnole.log(person.name) // 通过[]来访问 console.log(person["name"]) -
js数组
- js中允许通过下标在超过当前数组长度的位置插入元素,其中,中间未插入元素的部分元素值均为undefined
let arr=[1,2]; arr[100]=101; // 其中,下标位于2~99之间的元素均为undefined,数组长度为101- js中数组可以通过forEach方法对数组中每个值执行调用
let arr=[1,2]; // 将数组中的每个元素平方 arr.forEach((value,index,arr)=>{ arr[index]=value*value; }); -
js中的函数
- 函数在调用结束之后都会返回一个值,如果函数在结束时没有return语句,或是return语句后没有跟随值,都会返回一个undefined
- 在js函数中,可以通过展开运算符...来接受任意个数的参数,并且,对于数组,...也可以将其展开为被逗号分隔的参数列表
let arr = [1, 2, 3]; function sum(...arr) { let result = 0; for (let ele of arr) { result+=ele; } return result; } console.log(sum(...arr)); -
js中的嵌套函数
- 如果在js中,一个函数依赖与其他函数,但是依赖的其他函数并不会在其他地方被使用,那么可以将依赖的函数放在函数内部
function outer_func() { function inner_func() { // 除了被outer_func调用外不会在其他地方被调用 } }- 通过嵌套函数,可以有效的减少全局作用域中的函数名称,可以防止污染全局作用域的命名
-
js中的闭包
- 每当js中调用一次函数时,都会创建一个作用域对象,用来保存在函数中创建的局部变量。
- 当返回值为函数时,返回的函数中将会指向先前被创建的作用域对象,这样作用域对象在函数结束后就不会被回收
- 由于闭包可以保存状态,并且对外部隐藏状态,故而闭包可以代替对象来使用。闭包通过向外部返回一个操作内部局部变量的函数,保证位于内部的局部变量只能通过返回的函数来访问,保证了变量的安全
-
js继承和原型链
- 和面向对象的编程语言不同,js的继承是通过原型来实现的。每个对象都有一个原型对象,以原型为模板,从原型中继承方法和属性。原型对象也拥有原型,一层一层,以此类推,构成了原型链。
- 每一个对象都有内置的属性,其中,可以通过内置的__proto__属性来访问一个对象的prototype对象
- 原型链中属性的查找规则:
- 如果在一个对象中想要查找的属性不存在,那么将会在当前对象的prototype对象中查找属性
- 如果prototype对象中属性仍然找不到,那么就在prototype对象的prototype对象中查找属性
- 一直向前回溯,直到属性被找到或者回溯到原型链尾部
- 原型链结构:
- 对于所有的对象,默认__proto__指向的原型对象都是Object.prototype
- Obejct.prototype是位于原型链尾端的对象,Object.prototype的原型对象是null
- 为对象指定原型对象:
- 通过Object.create函数指定原型对象,该方法会创建一个新对象并为其指明原型对象
let proto_obj={ name: "kazusa", greeting() { console.log("hello, "+this.name); } }; let child_obj=Object.create(proto_obj); child_obj.greeting(); - 通过构造函数
- 在js中,所有函数都有一个prototype属性,当该函数被作为构造函数调用时,构造函数创建的所有新对象的__proto__属性都会被设置为该函数的prototype属性
- 在将构造函数的protype属性设置为制定的对象后,prototype对象中内置属性constructor发生了变化,需要重新将原型对象的constructor制定为构造函数
-
在js中实现类的继承
- js中,有如下关键字可以简化类的继承,其底层仍然使用原型链来实现类的继承关系
- class:用于类的声明
- extends:用于类的继承
- constructor:用于声明构造函数
- super():调用父类构造函数来实现子类构造函数
- js中,可以通过#字符来将变量或者方法标明为类私有的
- js中继承实现
class People { #name constructor(name) { this.#name = name } greeting() { console.log("hello, i am " + this.#name) } } class Student extends People { #grade constructor(name, grade) { super(name) this.#grade = grade } greeting() { console.log("hi, fucking bitch, miss your dad?") } } let p=new Student("touma",6) console.log(Object.getPrototypeOf(p))- js通过原型链实现继承的细节:
- js可以首先为父类创建构造函数
- js在子类的构造函数中,可以先调用ParentConstructor.call(this,args)方法来对子类的对象添加父类的成员变量
- 在完成子类对象成员变量的赋值后,可以通过Object.create创建一个以ParentConstructor.prototype为__proto__的新对象,并且将ChildConstructor.prototype设置为新对象
- 最后,将新对象的constructor属性设置为ChildConstructor
- js中,有如下关键字可以简化类的继承,其底层仍然使用原型链来实现类的继承关系