diff --git a/javascript/js.md b/javascript/js.md index 4cfc84d..f279cd3 100644 --- a/javascript/js.md +++ b/javascript/js.md @@ -31,4 +31,173 @@ - 但是在声明var变量的方法中,即使在声明var变量的语句之前,也可以使用var变量,变量值为undefined - js变量作用域特性: - 在js语言中,原本是没有块作用域的,变量只有函数范围的作用域。但是,通过引入const和let关键字,js支持声明块作用域的变量。 -- \ No newline at end of file +- ## js运算符 + - ==运算符和===运算符 + - ==运算符具有类型自适应的功能 + ```java + # 对于==运算符,如果运算符两边的类型不一致的话, + # 会尝试进行类型转换并比较 + 123==“123” true + 1==true true + ``` + - ===相对于==,比较前并不会进行强制类型转换 + ```java + 1===‘1’ false + 1===true false + ``` + - 相对应的,对于比较不相等的操作,也存在!=和!==操作,其区别类似于==和===的区别 +- ## js流程控制 + - js中for循环可以分为如下两种 + - for in循环: + - 对于for in循环,会遍历索引项(对数组来说是序号,对map来说是key,set为空) + - for of循环: + - 对于for of循环,会遍历值(value)而不是键(key) + - js中的switch流: + - 相比于c中的switch只支持数字,js中的switch既支持数字又支持字符串,switch和case之间是通过===运算符来判断是否严格相等的 +- ## js对象 + - js对象类似与map结构,由key和value组成的键值对构成 + - js对象的创建有如下两种方式 + - 字面量创建 + ```javascript + let obj={ + name:"touma", + id:"A001", + husband:{ + name:"haruki", + id:"A002" + } + } + ``` + - 通过对象原型来创建对象 + ```javascript + function Person(name,id) { + this.name=name + this.id=id + } + + let person=new Person("touma","A001") + ``` + - 访问对象元素的方式 + ```javascript + let person={ + name:"touma", + id:"A001" + } + // 通过.来访问 + cosnole.log(person.name) + // 通过[]来访问 + console.log(person["name"]) + ``` +- ## js数组 + - js中允许通过下标在超过当前数组长度的位置插入元素,其中,中间未插入元素的部分元素值均为undefined + ```javascript + let arr=[1,2]; + arr[100]=101; + // 其中,下标位于2~99之间的元素均为undefined,数组长度为101 + ``` + - js中数组可以通过forEach方法对数组中每个值执行调用 + ```javascript + let arr=[1,2]; + // 将数组中的每个元素平方 + arr.forEach((value,index,arr)=>{ + arr[index]=value*value; + }); + ``` +- ## js中的函数 + - 函数在调用结束之后都会返回一个值,如果函数在结束时没有return语句,或是return语句后没有跟随值,都会返回一个undefined + - 在js函数中,可以通过展开运算符...来接受任意个数的参数,并且,对于数组,...也可以将其展开为被逗号分隔的参数列表 + ```javascript + 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中,一个函数依赖与其他函数,但是依赖的其他函数并不会在其他地方被使用,那么可以将依赖的函数放在函数内部 + ```javascript + 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函数指定原型对象,该方法会创建一个新对象并为其指明原型对象 + ```javascript + 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中继承实现 + ```javascript + 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 \ No newline at end of file