js-day01

85 阅读9分钟

1、当我们使用数组的splice(开始索引,多少个,添加的数据)方法进行删除数据的操作时,会导致数据的索引前移,本来应该删除的不能被删除掉,会造成数组的塌陷问题。

解决方案:第一种是倒着循环;第二种是在执行完arr.splice(i,1)之后执行一个减减(--)的操作。

2、箭头函数没有arguments

3、ES6中的模块化开发:模块化开发不涉及到样式和结构,指的就是交互的逻辑的实现,一个模块就是一个独立的个体,一个.js文件就是一个模块。在模块中定义的变量只能在当前模块中使用,别的模块中不能使用。ES6中的模块化就是相对独立的一个js文件。
导入:import 变量名 from '导入的文件的路径'
导出:export default 你要导出的数据
export default {你要导出的数据}

4、自定义构造函数时,关键字new做了什么:自动创建一个空对象,让this指向这个空对象,手动添加成员,自动返回这个对象

function createObj(name,age,location){
    // 让this指向这个空对象(this就是这个空对象)
    this.name = name
    this.age = age
    this.location = location
    // 因为new会自动返回这个空对象,所以不用return
}
// 使用的时候
let res = new createObj('dlrb',33,'新疆')
console.log(res)

5、原型对象和对象原型 原型对象是函数自带的属性,叫做prototype。

对象的访问:当要访问一个成员(属性或者方法)的时候,首先在自己身上查找,如果有就拿来使用,停止查找,如果没有,就去到所属构造函数的原型对象上查找,如果有,就拿来使用。如果没有就继续到所属构造函数的原型对象上查找。以此类推,直到找到顶级原型,如果有就拿来使用,如果没有就返回undefined

6、ES6中的类(class)

// 语法
class 类名(其实就是ES5中的函数名) {
     constructor(参数) {
      注释: 属性
}
class 类名(其实就是ES5中的函数名) {
     constructor(参数) {
           注释: 属性
     }
      注释: 这里定义方法
      注释: 这个方法就是定义在原型对象上
}
class Person{
    constructor(name,age){
        // 属性
        this.name = name
        this.age = age
    }
    // 方法
    sayHi(){}
}
let p = new Person('Rose', 20)
console.log(p);
console.log(p.name);
console.log(p.age);
console.log(p.sayHi);
p.sayHi()

7、常见的继承方式
第一种:原型继承.就是把子类的原型对象指向父类的实例。或者说把父类的实例赋值给子类的原型对象。优点:既可以继承父类的属性,也可以继承父类的方法,继承下来的属性不在自己身上,在原型对象上,继承下来的属性的值不能任意修改,需要在多个地方传递参数。

image.png

第二种:借用构造函数继承。就是把父类构造函数当作普通函数来调用,在子类构造函数中调用,通过call()来改变this指向。优点:可以继承父类的属性,继承下来的属性在自己身上,可以传递任何想要传递的参数,只需要在一个地方传递参数就可以了。 缺点:不能继承父类的方法

image.png

第三种:组合继承。原型继承和借用构造函数继承结合使用。优点:既可以继承属性也可以继承方法。继承下来的属性在自己身上,也可以在一个地方传递参数,也可以传递任意的参数。缺点:在子类的原型对象上多了一套属性,如果赋值,就是赋的值,。如果没有赋值,就是undefined。

 function Person(name,age){
       this.name = name 
       this.age = age
}
Person.prototype.aaa = function(){console.log('aaaa')}
function Students(classRoom,name,age){
      // 子类的构造函数体中
      this.classRoom = classRoom
       // 构造函数继承
       Person.call(this,name,age)
}
// 原型继承
Students.prototype = new Person()
let s = new Students('一班','张三','32岁')
console.log(s);
console.log(s.classRoom);
console.log(s.name);   //一班
console.log(s.age);   // 32岁
console.log(s.aaa);  // 函数体
s.aaa()  // aaaa



第四种:ES6中类的继承。在ES6中关于继承已经升级到了语法层次。需要在子类的构造函数中书写super():就是用来继承父类的属性的。super()必须要有,而且要书写在子类构造函数体中的所有的this的前面。

// 语法
class 子类 extends 父类 {
     constructor() {
             属性
      }
      方法
}
super()是用来继承方法的

image.png

第五种:拷贝继承。主要利用for...in循环来实现的,更多的是利用我们的in这个关键字。(in关键字不仅可以判断函数体中的属性,也可以判断原型对象上的属性)

function Person(name,age){
        this.name = name
        this.age = age
}
Person.prototype.aa = function(){console.log('aa')}
Person.prototype.a = 200
// 实例化一个对象
let p = new Person('rose',20) 
console.log('name' in p)     //true
console.log('age' in p)     //true
console.log('name1' in p)    //false
console.log('a' in p)   //true
console.log('aa' in p)   //true

第六种:深浅拷贝。指的是对数组或者是对对象的一种复制,复制完成以后,修改其中的一个,另一个不会受到影响。深浅拷贝的时候,不考虑基本数据类型,因为基本数据类型没有引用地址一说。 复制的三个阶段:赋值、浅拷贝、深拷贝。

深拷贝的核心是递归函数

// 方法一
let o1 = {
     name:'jack',
     age:18,
     info:{
            height:'180cm',
            weight:'60kg',
            lover:{
                sex:'woman'
            }
       },
      hobby:['吃饭','睡觉','打豆豆']
}
// 创建一个新的空对象
 let o2 = {}

image.png

// 方法二(利用我们的JSON格式字符串来实现)
// 第一步:把js数据类型转成JSON格式字符串
// 第二步:把刚刚转完的JSON格式字符串再转换成js数据格式
// 注意:函数和undefined易丢失
let o1 = {
        name:'jack',
        age:18,
        info:{
            height:'180cm',
            weight:'60kg',
            lover:{
                sex:'woman'
            }
        },
        hobby:['吃饭','睡觉','打豆豆']
}
let a = JSON.stringify(o1)
let res = JSON.parse(a)
res.name = 'lili'
res.info.lover.sex = '女生'
console.log(res)

8、闭包
在一个作用域中可以访问另一个函数内部的局部变量的函数,实际上是利用了js中作用域链的概念,就是说,如果在某个作用域下访问某个变量的时候,如果不存在,就一直向外层寻找,直到在全局作用域下找到对应的变量为止,这里就形成了所谓的作用域链。
闭包的特性:闭包可以访问到父级函数的变量,访问到父级函数的变量不会销毁。
function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();

9、防抖和节流:用来降低触发频率的。
防抖:防抖是指在一定时间内,事件触发后延迟执行回调函数,如果在延迟时间内再次触发了该事件,则重新计时。这样可以避免事件的频繁触发,减少不必要的计算和请求。在Vue中,我们经常会遇到一些需要防抖处理的场景,比如输入框输入关键字后进行搜索,滚动页面加载更多数据等。通过使用防抖技巧,我们可以减少请求次数,节省服务器资源,并提升用户体验。
节流:节流是指在一定时间内,事件仅触发一次。无论触发频率多高,都会按照固定的时间间隔执行回调函数。这样可以减少回调函数的执行次数,提高页面的性能。 在Vue中,节流常常用于处理一些需要频繁触发的事件,比如窗口滚动、鼠标移动等。通过使用节流技巧,我们可以确保事件的触发频率不会过高,从而减少不必要的计算和渲染。

10、数据扁平化(就是把多维数组变成一维数组)
方法一:

image.png

方法二:toString()。对复杂数据类型不友好

image.png

方法三:flat()

语法:数组.flat(数字)
数字:表示的是要展开的层数
不传递数字的时候默认展开一层,传递Infinity,表示从第一层展开到末尾

image.png

11、认识Promise:是ES6中出现的一个构造函数,出现的目的就是为了解决回调地狱。回调函数的出现是为了异步代码的封装,回调函数的嵌套使用会形成回调地狱。Promise是为了解决回调地狱,就是使用Promise的语法来封装异步代码。

语法:const 变量名 = new Promisefunction(参数){异步代码})
返回值:是一个实例,也是一个对象
参数:这里接受两个参数,是两个状态转换函数
第一个:当调用Promise时,从持续转换为成功
第二个:当调用Promise时,从持续转换为失败
Promise的三个状态:pending(持续状态)、fulfilled(成功状态)、rejected(失败状态)
Promise的状态只能转换一次,要不从持续状态转成功,要不就是从持续转失败
实例p常用的方法:then(函数),当成功的时候调用then()方法中的函数。catch(函数),当失败的时候调用catch()方法中的函数

image.png

async和await:是两个关键字。
async:异步的意思,是一个关键字,书写在函数的前面,把这个函数编程异步函数,就是将来为了使用await
await:等待的意思:也是一个关键字,书写在带有async的函数中。作用:await后面等待的必须是一个Promise对象,之后后面的Promise对象给结果才向后继续执行。没有结果就一直等待。
把async和await解决回调地狱叫做终极解决回调地狱。

image.png

image.png
await后面等待的必须是Promise对象,p就是那个对象

image.png
await后面只能等到成功的结果,失败的就不能等到了

实例上面的方法

image.png

构造函数身上的

image.png

12、前后端交互ajax(a:async;j:javascript;a:and;x:xml是严格意义上的html)

image.png

image.png

image.png

image.png

image.png

三次握手、四次挥手以及http状态码

13、请求测试

带有参数的get请求 image.png

带有参数的post请求 image.png

get请求携带参数携带请求头(get只能携带查询字符串) image.png

14、canvas画布

15、深浅拷贝:深拷贝和浅拷贝
首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别。
浅拷贝:只是拷贝了基本类型的数据。而引用类型数据,复制后也是会发生引用,把这种拷贝叫做浅拷贝,浅拷贝仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅拷贝出来的对象也会相应改变。
深拷贝:在计算机中开辟了一块新的内存地址用来存放复制的对象