JavaScript------面向对象

news2024/11/30 1:39:26

目录

一、面向对象编程(OOP) 基本概念

二、类

1、语法

2、通过类创建对象

3、类的属性

4、类的方法

5、构造函数

三、面向对象的三个特点

1、封装

如何确保数据的安全(实现封装的方式):

2、继承

在子类中,可以通过创建同名方法来重写父类的方法。

在子类中,可以重写构造函数。

OCP 开闭原则

3、多态

四、对象的内存结构

1、对象自身

2、原型对象(prototype)

五、原型对象

1、访问一个对象的原型对象

2、原型对象中的数据

3、原型链

4、原型的作用

作用:

对比函数的原型链和Object的原型链

5、修改原型

6、检查对象自身或原型上是否有某属性的方法

6.1、instanceof

6.2、in运算符

6.3、hasOwnProperty(不推荐)

6.4、hasOwn

六、旧类

七、new运算符

八、总结


一、面向对象编程(OOP) 基本概念

1. 程序是干嘛的?  - 程序就是对现实世界的抽象(照片就是对人的抽象)

2. 对象是干嘛的?- 一个事物抽象到程序中后就变成了对象。 在程序的世界中,一切皆对象

3. 面向对象的编程 - 面向对象的编程指,程序中的所有操作都是通过对象来完成。做任何事情之前都需要先找到它的对象,然后通过对象来完成各种操作。

  • 一个事物通常由两部分组成:数据和功能
  • 一个对象由两部分组成:属性和方法
  • 事物的数据到了对象中,体现为属性
  • 事物的功能到了对象中,体现为方法

二、类

使用Object创建对象的问题: 1. 无法区分出不同类型的对象; 2. 不方便批量创建对象

在JS中可以通过类(class)来解决这个问题:类是对象模板,可以将对象中的属性和方法直接定义在类中。定义后,就可以直接通过类来创建对象。

可以说,创建对象的第一步,就是为这个对象定义一个类。

1、语法

方式一:
class 类名 {} // 类名要使用大驼峰命名

方式二:
const 类名 = class {}  
const Person = class {}

// Person类专门用来创建人的对象
class Person{

}

// Dog类式专门用来创建狗的对象
class Dog{

}

2、通过类创建对象

语法:new 类()

const p1 = new Person()  // 调用构造函数创建对象
console.log(p1)   // Person{}

Person()相当于把类当做一个函数在调用,加上new就是构造函数

通过同一个类创建的对象,我们称为同类对象。可以使用instanceof来检查一个对象是否是由某个类创建。

const p1 = new Person()  // 调用构造函数创建对象
const p2 = new Person()

const d1 = new Dog()
const d2 = new Dog()

console.log(p1 instanceof Person) // true
console.log(d1 instanceof Person) // false

如果某个对象是由某个类所创建,则我们称该对象是这个类的实例。以上代码中p1、p2是Person类的实例,d1、d2是Dog类的实例。

3、类的属性

类是创建对象的模板,要创建第一件事就是定义类。

类的代码块,默认就是严格模式,类的代码块是用来设置对象的属性的,不是什么代码都能写的。

  1. 实例属性只能由实例对象访问的
  2. static声明的属性,只能通过类访问,实例对象是无法访问的
class Person{
      name = "孙悟空" // Person的实例属性name, p1.name、p2.name
      age = 18       // 实例属性只能通过实例访问, p1.age、p2.age
      static test = "test静态属性" // 使用static声明的属性,是静态属性(类属性) Person.test
      static hh = "静态属性"   // 静态属性只能通过类去访问, Person.hh   实例对象中是没有的
}

4、类的方法

添加方法的方式有2种。

class Person{

    name = "孙悟空"

    // 添加方法的一种方式(不推荐使用,{}内有无内容,打印p1时都会显示该方法)
    // sayHello = function(){
    // } 
    
    // 添加方法(实例方法),方法中也就是{}中没写内容,打印p1时不会显示sayHello,但是方法已经加入到Person中了 
    sayHello(){
        console.log('大家好,我是' + this.name)   // 实例方法中this就是当前实例p1
    } 

    // 静态方法(类方法) 通过类来调用 
    static test(){
          console.log("我是静态方法", this)   // 静态方法中this指向的是当前类Person
    } 
}


const p1 = new Person()
console.log(p1)
Person.test()
p1.sayHello()   // 哈哈哈

5、构造函数

当我们在类中直接指定实例属性的值时,意味着我们创建的所有对象的属性都是这个值。因此,希望每次new类对象时,每个实例对象的属性的值都是不一样的。

在类中可以添加一个特殊的方法constructor,该方法我们称为构造函数(构造方法),构造函数会在我们调用类创建对象时执行。

class Person{
    constructor(name, age, gender){
         console.log("构造函数执行了~")     // 构造函数会在我们调用类创建对象时执行
    }
}

const p1 = new Person()
console.log(p1)    //  构造函数执行了~


class Person{
    constructor(name, age, gender){
    // 可以在构造函数中,为实例属性进行赋值,用this
    // 在构造函数中,this表示当前所创建的对象
         this.name = name   // 将参数的name赋值给Person对象的name实例属性
         this.age = age
         this.gender = gender
    }
}

const p1 = new Person("孙悟空", 18, "男")   // 向Person里传的参数,实际上就是传给构造函数
const p2 = new Person("猪八戒", 28, "男")
const p3 = new Person("沙和尚", 38, "男")

console.log(p1)    // {name:"孙悟空", age:18,gender:"男"}
console.log(p2)    // {}
console.log(p3)    // {}

三、面向对象的三个特点

面向对象的特点:封装(安全性)、继承(扩展性)和多态(灵活性)

1、封装

装:对象就是一个用来存储不同属性的容器。

封:对象不仅存储属性,还要负责数据的安全,保证数据的合法性(比如年龄不能为负数)。直接添加到对象中的属性,并不安全,因为它们可以被任意的修改。

如何确保数据的安全(实现封装的方式):

1.私有化数据

将需要保护的数据设置为私有,只能在类内部使用

class Person {
    #address = "花果山" // 实例使用#开头就变成了私有属性,私有属性只能在类内部访问
    sayHello() {
         console.log(this.#address)
     }
}

const p1 = new Person()

console.log(p1.#address)  // 报错,私有属性不能访问
console.log(p1.sayHello())  // 花果山

私有化属性一定要先声明再使用,否则会报错

class Person {
        #name
        #age
        #gender
        constructor(name, age, gender) {
             this.#name = name
             this.#age = age
             this.#gender = gender
        }


const p1 = new Person("孙悟空", 18, "男")
console.log(p1)  // Person{#name: "孙悟空",#age: 18,#gender: "男"}

p1.#age = 11  // 报错,私有属性无法访问,更无法更改

2.提供setter和getter方法来开放对数据的操作

属性设置私有,通过getter setter方法操作属性带来的好处:

  • ①可以控制属性的读写权限:数据只读,就只有getter方法;数据只写,只有setter方法;数据可读写,有getter和getter方法;数据不可读也不可写,getter和getter方法都无;
  • ②可以在方法中对属性的值进行验证:在方法中添加一些数据的条件,如年龄不能为负数
class Person {
    #name
    #age
    #gender

    constructor(name, age, gender) {
         this.#name = name
         this.#age = age
         this.#gender = gender
    }

    // getter方法,用来读取属性
    getName(){
         return this.#name
    }

    // setter方法,用来设置属性
    setName(name){
          this.#name = name
    }

    getAge(){
          return this.#age
    }

    setAge(age){
          if(age >= 0){
               this.#age = age
           }
    }

}

const p1 = new Person("孙悟空", 18, "男")

p1.getName()
p1.setName('猪八戒')

console.log(p1)  // Person{#name: "猪八戒",#age: 18,#gender: "男"}

为了访问属性时不用像上面的getter方法一样麻烦,可以这么写访问函数:

class Person {
    #gender
    constructor(gender) {
         this.#gender = gender
    }

    get gender(){
         return this.#gender
    }

    set gender(gender){
         this.#gender = gender
    }
}

const p1 = new Person("孙悟空", 18, "男")

// 读取属性的值,调用get方法
console.log(p1.gender)  // 男    

// 修改属性的值,调用set方法
p1.gender = "女" 
console.log(p1.gender)  // 女

2、继承

通过extends关键来完成继承。当一个类继承另一个类时,就相当于将另一个类中的代码复制到了当前类中(简单理解)。继承发生时,被继承的类称为 父类(超类),继承的类称为 子类。通过继承可以减少重复的代码,并且可以在不修改一个类的前提对其进行扩展。

class Animal{
      constructor(name){
                this.name = name
      }

      sayHello(){
                console.log("动物在叫~")
      }
}

class Dog extends Animal{
            
}

class Cat extends Animal{
            
}

const dog = new Dog("旺财")
const cat = new Cat("汤姆")

dog.sayHello()  // 动物在叫~
cat.sayHello()  // 动物在叫~

不用继承,以上代码就会重复冗余,写成如下形式:

class Dog extends Animal{
      constructor(name){
                this.name = name
      }

      sayHello(){
                console.log("动物在叫~")
      }
}

class Cat extends Animal{
      constructor(name){
                this.name = name
      }

      sayHello(){
                console.log("动物在叫~")
      }
}

const dog = new Dog("旺财")
const cat = new Cat("汤姆")

dog.sayHello()  // 动物在叫~
cat.sayHello()  // 动物在叫~

在子类中,可以通过创建同名方法来重写父类的方法。

class Animal{
      constructor(name){
                this.name = name
      }

      sayHello(){
                console.log("动物在叫~")
      }
}

class Dog extends Animal{
      sayHello(){
                console.log("汪汪汪")
      }
}

class Cat extends Animal{
      sayHello(){
                console.log("喵喵喵")
      }            
}

const dog = new Dog("旺财")
const cat = new Cat("汤姆")

dog.sayHello()  // 汪汪汪
cat.sayHello()  // 喵喵喵

在子类中,可以重写构造函数。

重写构造函数时,构造函数的第一行代码必须为super(),表示继承父类的构造函数。

class Animal{
      constructor(name){
                this.name = name
      }

      sayHello(){
                console.log("动物在叫~")
      }
}

class Cat extends Animal{
      // 重写构造函数
      constructor(name, age){   // 一定要写传入的参数,否则属性值为undefined
           // 重写构造函数时,构造函数的第一行代码必须为super()
           super(name) // 调用父类的构造函数,继承了父类的name属性,所以一定要写name参数
          //如果不写,那就自己重写name属性=》this.name = name
           this.age = age
      }
      sayHello(){
           super.sayHello()  // 在方法中使用super来继承父类的方法
           console.log("喵喵喵")
      }            
}

const cat = new Cat("汤姆", 3)

console.log(cat)   // Cat{name:"汤姆", age: 3}

cat.sayHello()  // 动物在叫~     喵喵喵

OCP 开闭原则

程序应该对修改关闭,对扩展开放。尽量不修改父类,而是用一个子类继承父类,父类的方法、属性中子类需要的就保留,不需要的就不要,然后在子类再扩展一些子类需要的属性、方法。

3、多态

在JS中不会检查参数的类型,所以这就意味着任何数据都可以作为参数传递。要调用某个函数,无需指定的类型,只要对象满足某些条件即可。多态为我们提供了灵活性

class Person{
    constructor(name){
          this.name = name
     }
}

class Dog{
    constructor(name){
          this.name = name
     }
}

const dog = new Dog('旺财')
const person = new Person("孙悟空")

function sayHello(obj){
      console.log("Hello,"+obj.name)
}

sayHello(dog)   // Hello, 旺财
sayHello(person)   // Hello, 孙悟空

四、对象的内存结构

对象中存储属性的区域实际有两个:对象自身和原型对象

1、对象自身

直接通过对象所添加的属性,位于对象自身中。

在类中通过 属性名 = 属性值 的形式添加的属性,位于对象自身中。

2、原型对象(prototype)

对象中还有一些内容,会存储到其他的对象里(原型对象)。

在对象中会有一个属性用来存储原型对象,这个属性叫做__proto__

原型对象也负责为对象存储属性,当我们访问对象中的属性时,会优先访问对象自身的属性,对象自身不包含该属性时,才会去原型对象中寻找。

 会添加到原型对象中的情况:

  • 在类中通过xxx(){}方式添加的方法,位于原型中
  • 主动向原型中添加的属性或方法
class Person {
     name = "孙悟空"
     age = 18

     constructor(){
          this.gender = "男"
     }

     sayHello() {
           console.log("Hello,我是", this.name)
     }
}

const p = new Person()

console.log(p.sayHello)   // Hello,我是孙悟空


p.sayHello = "hello"
console.log(p.sayHello)   // hello    先从自身属性找sayHello
  

在内存中,上述代码的表现:

五、原型对象

1、访问一个对象的原型对象

语法:对象.__proto__   or   Object.getPrototypeOf(对象)

PS:浏览器不建议使用对象.__proto__去访问对象的原型对象,所以提供了Object.getPrototypeOf(对象)去访问对象的原型对象

class Person {
    name = "孙悟空"
    age = 18

    sayHello() {
         console.log("Hello,我是", this.name)
    }
}

const p = new Person()

console.log(p)   // {name:"孙悟空", age: 18}
console.log(p.__proto__)  // {constructor:f, sayHello: f}
console.log(Object.getPrototypeOf(p))    // {constructor:f, sayHello: f}

2、原型对象中的数据

  • 1. 对象中的数据(属性、方法等)
  • 2. constructor (对象的构造函数),类里面没有就找原型的构造函数
class Person {
    name = "孙悟空"
    age = 18

    sayHello() {
         console.log("Hello,我是", this.name)
    }
}

const p = new Person()


// Person类里面没有constructor,所以去原型里找
console.log(p.__proto__.constructor)  // 打印整个class Person
console.log(p.constructor)  // 打印整个class Person

原型对象也有原型。这样就构成了一条原型链。

class Person {
    name = "孙悟空"
    age = 18

    sayHello() {
         console.log("Hello,我是", this.name)
    }
}

const p = new Person()


console.log(p.__proto__.__proto__)  // 原型对象也有原型
console.log(p.__proto__.__proto__.__proto__)  // null

根据对象的复杂程度不同,原型链的长度也不同。空对象的原型存在、原型的原型不存在。

class Person {
    name = "孙悟空"
    age = 18

    sayHello() {
         console.log("Hello,我是", this.name)
    }
}

const p = new Person()


console.log(p.__proto__.__proto__)  // 原型对象也有原型
console.log(p.__proto__.__proto__.__proto__)  // null


const obj = {}
console.log(obj.__proto__)    // 存在
console.log(obj.__proto__.__proto__)    // null

3、原型链

读取对象属性时,会优先对象自身属性,如果对象中有,则使用,没有则去对象的原型中寻找如果原型中有,则使用,没有则去原型的原型中寻找,直到找到Object对象的原型(Object的原型没有原型(为null))。如果依然没有找到,则返回undefined。

作用域链与原型链的区别:

  • 作用域链,是找变量的链,找不到会报错
  • 原型链,是找属性的链,找不到会返回undefined

4、原型的作用

所有的同类型对象它们的原型对象都是同一个,也就意味着,同类型对象的原型链是一样的

class Person {
    name = "孙悟空"
    age = 18

    sayHello() {
         console.log("Hello,我是", this.name)
    }
}

const p = new Person()
const p2 = new Person()

console.log(p === p2)  // false
console.log(p.__proto__ === p2.__proto__)  // true


const d = new Dog()
console.log(d === p)  // false
console.log(d.__proto__ === p.__proto__)  // false,因为d和p不同类

作用:

原型就相当于是一个公共的区域,可以被所有该类实例访问,可以将该类实例中,所有的公共属性(方法)统一存储到原型中。这样我们只需要创建一个属性,即可被所有实例访问

在对象中有些值是对象独有的,像属性(name,age,gender)每个对象都应该有自己值,但是有些值对于每个对象来说都是一样的,像各种方法,对于一样的值没必要重复的创建。

如果只有少数对象的方法与其他的不一样,那么就实例.方法 = 新方法内容进行修改即可。

JS中继承就是通过原型来实现的,当继承时,子类的原型就是一个父类的实例。

class Animal{
}

class Cat extends Animal{
}

class TomCat extends Cat{
}

const cat = new Cat()
console.log(cat)   // Cat{}
console.log(cat.__proto__)   // Animal{}

cat --> Animal实例 --> object --> Object原型 --> null
TomCat --> cat --> Animal实例 --> object --> Object原型 --> null

所有类都是object的子类

对比函数的原型链和Object的原型链

  • 函数的原型链:
    function A(){
    };
    var f1 = new A();
    
    f1.proto ==>A.prototype ==> A.prototype.proto ==> Object.prototype ==> Object.prototype.proto ==> null
    
    
    ---------------------------------------------------------
    
    function A(){
    };
    
    A.proto ==>Function.prototype ==>Function.prototype.proto ==> Object.prototype ==> Object.prototype.proto ==> null
    
  • Object的原型链:

5、修改原型

通过类的prototype属性,修改应在类定义好之后。好处:①一修改就是修改所有实例的原型,②无需创建实例即可完成对类的修改

语法:类.prototype

通过类的实例去修改原型,原则上不太好,因为是通过一个对象影响所有同类对象,这么做不合适。

class Person {
     name = "孙悟空"
     age = 18

     sayHello() {
         console.log("Hello,我是", this.name)
     }
}
            
Person.prototype.fly = () => {
      console.log("我在飞!")
}

最好不要直接给prototype去赋值,因为会把原来的东西覆盖掉

6、检查对象自身或原型上是否有某属性的方法

6.1、instanceof

作用:检查一个对象是否是一个类的实例。检查的是对象的原型链上是否有该类实例,只要原型链上有该类实例,就会返回true。

Object是所有对象的原型,所以任何和对象和Object进行instanceof运算都会返回true。

class Animal {}

class Dog extends Animal {}

const dog = new Dog()

console.log(dog instanceof Dog) // true
console.log(dog instanceof Animal) // true
console.log(dog instanceof Object) // true

dog(Dog的实例) -> Animal的实例 -> Object实例 -> Object原型

6.2、in运算符

使用in运算符检查属性时,无论属性在对象自身还是在原型中,都会返回true

class Person {
    name = "孙悟空"
    age = 18

    sayHello() {
         console.log("Hello,我是", this.name)
    }
}

const p = new Person()
 
console.log("name" in p)   // true
console.log("sayHello" in p)   // true

6.3、hasOwnProperty(不推荐)

作用:用来检查一个对象的自身是否含有某个属性,有则返回true。原型上的属性返回false。

语法:对象.hasOwnProperty(属性名)

class Person {
    name = "孙悟空"
    age = 18

    sayHello() {
         console.log("Hello,我是", this.name)
    }
}

const p = new Person()
 
console.log(p.hasOwnProperty("name"))   // true
console.log(p.hasOwnProperty("sayHello"))   // false
console.log(p.__proto__.__proto__.hasOwnProperty("hasOwnProperty"))  // true

6.4、hasOwn

作用:新增的静态方法,用来检查一个对象的自身是否含有某个属性。

语法:Object.hasOwn(对象, 属性名)

class Person {
    name = "孙悟空"
    age = 18

    sayHello() {
         console.log("Hello,我是", this.name)
    }
}

const p = new Person()
 
console.log(Object.hasOwn(p, "name"))   // true
console.log(Object.hasOwn(p, "sayHello"))   // false

六、旧类

早期JS中,直接通过函数来定义类。

一个函数如果直接调用 xxx() 那么这个函数就是一个普通函数。一个函数如果通过new调用 new xxx() 那么这个函数就是一个构造函数。

// 用立即执行函数将对象的所有代码包裹起来
var Person = (function() {
   function Person(name, age) {
      // 在构造函数中,this表示新建的对象
      this.name = name
      this.age = age
  
      // this.sayHello = function(){
      //     console.log(this.name)
      // }
  }

   // 向原型中添加属性(方法)
   Person.prototype.sayHello = function () {
      console.log(this.name)
   }

   // 静态属性
   Person.staticProperty = "xxx"

   // 静态方法
   Person.staticMethod = function () {}

   return Person

})()

旧类的继承:

var Animal = (function(){
    function Animal(){
     }

     return Animal
})()

var Cat = (function(){
     function Cat(){
      }

     // 继承Animal
     Cat.prototype = new Animal()

     return Cat
})()

var cat = new Cat()

console.log(cat)

七、new运算符

官网:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new

当使用new去调用一个函数时,这个函数将会作为构造函数调用,使用new调用函数时,将会发生这些事:

  • 1. 创建一个普通的JS对象(Object对象 {}), 为了方便,称其为新对象
  • 2. 将构造函数的prototype属性设置为新对象的原型
  • 3. 使用实参来执行构造函数,并且将新对象设置为函数中的this
  • 4. 如果构造函数返回的是一个非原始值,则该值会作为new运算的返回值返回(千万不要这么做)。如果构造函数的返回值是一个原始值或者没有指定返回值,则新的对象将会作为返回值返回。通常不会为构造函数指定返回值。

八、总结

面向对象本质就是,编写代码时所有的操作都是通过对象来进行的。

面向对象的编程的步骤:

          1. 找对象

          2. 搞对象:调用属性、修改属性、调用方法、修改方法

学习对象:

          1. 明确这个对象代表什么,有什么用    

          2. 如何获取到这个对象

          3. 如何使用这个对象(对象中的属性和方法)

对象的分类:

         内建对象

                 - 由ES标准所定义的对象

                 - 比如 Object Function String Number ....

         宿主对象

                  - 由浏览器提供的对象

                  - BOM、DOM

         自定义对象

                  - 由开发人员自己创建的对象

           

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/344580.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode】每日一题(4)

目录 题目:1124. 表现良好的最长时间段 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 题目:1124. 表现良好的最长时间…

算法思想 - 回溯算法

Backtracking(回溯)属于 DFS, 本文主要介绍算法中Backtracking算法的思想。回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种…

ChatGPT 类 AI 软件供应链的安全及合规风险

AIGC将成为重要的软件供应链近日,OpenAI推出的ChatGPT通过强大的AIGC(人工智能生产内容)能力让不少人认为AI的颠覆性拐点即将到来,基于AI将带来全新的软件产品体验,而AI也将会成为未来软件供应链中非常重要的一环。在O…

【项目精选】基于WEB的仓库管理系统的设计与实现(论文+视频+源码)

点击下载源码 仓库物品的管理是与我们的日常生活息息相关的一个重大问题。随着我国经济飞速的发展,改革开放的不断深入,企业要想在激烈的市场竞争中立于不败之地,要想继续的发展与生存,没有现代化的管理方式与方法是万万不行的&am…

torch.nn.parameter 生成可更新的 tensor (requires_grad = True)

torch.nn.parameter 是 PyTorch 中的一种特殊类型的 tensor,它主要用于存储神经网络中的参数。这些参数可以被自动求导和被优化器自动更新。使用 torch.nn.Parameter 定义的tensor 会被自动添加到模型的参数列表中。 \quadtorch.nn.Parameter 是继承自 torch.Tensor…

vite+vue3搭建的工程热更新失效问题

前段时间开发新的项目,由于没有技术上的限制,所以选择了vitevue3ts来开发新的项目,一开始用vite来开发新项目过程挺顺利,确实比vue2webpack的项目高效些(为什么选择vite),但是过了一段时间后,不…

android组件化

学习流程:1.开源最佳实践:Android平台页面路由框架ARouter-阿里云开发者社区 (aliyun.com)2.中文ARouter使用API:https://github.com/alibaba/ARouter/blob/master/README_CN.md3.看当前文档后面的代码4.这是通俗易懂的文章:https…

使用 Nodejs、Express、Postgres、Docker 在 JavaScript 中构建 CRUD Rest API

让我们在 JavaScript 中创建一个 CRUD rest API,使用:节点.js表达续集Postgres码头工人码头工人组成介绍这是我们将要创建的应用程序架构的架构:我们将为基本的 CRUD 操作创建 5 个端点:创造阅读全部读一个更新删除我们将使用以下…

【H.264】码流解析 annexb vs avcc

H264码流解析及NALUAVCC和ANNEXB 前者是FLV容器、mp4 常用的。后者 是实时传输使用,所以是TS 一类的标准。VLC显示AVC1就是AVCC AVCC格式 也叫AVC1格式,MPEG-4格式,字节对齐,因此也叫Byte-Stream Format。用于mp4/flv/mkv, VideoToolbox。 – Annex-B格式 也叫MPEG-2 trans…

微信公众号扫码授权登录思路

引言 上学期研究了一下微信登录相关内容,也写了两三篇笔记,但是最后实际登录流程没有写,主要因为感觉功能完成有所欠缺,一直也没有好的思路;这两天我又看了看官方文档,重新构思了一下微信公众号登录相关的…

操作系统综合实验

实验目的 加深对进程概念理解,进一步认识进程并发执行掌握Linux系统的进程创建和终止操作掌握文件系统调用及文件标准子例程的编程方法掌握Linux下终端图形编程方法,能编写基于文本的图形界面掌握proc文件系统的使用 相关知识 Linux C编程中的头文件 …

知识点整合

⭐面试 自我介绍(优势岗位匹配度) 为什么来我们公司(对公司的了解) 讲讲做的项目(为什么这么做,思路和贡献) 跨部门涉案的业务流程 我们跨部门涉案业务主要是本系统、配合物流系统和罚没系…

二战字节跳动成功上岸,准备了小半年,拿27k也算不上很高吧~

先说下我基本情况,本科不是计算机专业,现在是学通信,然后做图像处理,可能面试官看我不是科班出身没有问太多计算机相关的问题,因为第一次找工作,字节的游戏专场又是最早开始的,就投递了&#xf…

SpringMVC传值

实现步骤 先看后台代码如何获取前端传过来的数据,直接在方法的参数列表中添加RequestParam(xxx),再在后面加上参数列表即可 不过这样的方式会出现一个问题:当前端页面没有提交相应的数据过来的时候,后台会出现异常,所…

Elasticsearch7.8.0版本进阶——数据读流程

目录一、数据读流程概述二、数据读流程步骤2.1、数据读流程图2.2、数据读流程步骤(从主分片或者副本分片检索文档的步骤顺序)2.3、数据读流程注意事项一、数据读流程概述 从主分片或者从其它任意副本分片检索文档。 二、数据读流程步骤 2.1、数据读流…

5_机试_递归和分治

一、递归 本章介绍程序设计中的另一个非常重要的思想一递归策略。递归是指函数直接或间接调用自身的一种方法,它通常可把一个复杂的大型问题层层转化为与原问题相似但规模较小的问题来求解。递归策略只需少量的程序就可描述解题过程所需的多次重复计算,…

谈谈Java多线程离不开的AQS

如果你想深入研究Java并发的话,那么AQS一定是绕不开的一块知识点,Java并发包很多的同步工具类底层都是基于AQS来实现的,比如我们工作中经常用的Lock工具ReentrantLock、栅栏CountDownLatch、信号量Semaphore等,而且关于AQS的知识点…

DDR4 信号说明

SDRAM Differential Clock :Differential clocks signal pairs , pair perrank . The crossing of the positive edgeand the negative edge of theircomplement are used to sample thecommand and control signals on theSDRAMSDRAM差分时钟:差分时钟信号对&#…

MagicThoughts|让ChatGPT变得更智能的Finetuned数据集

近两个月,ChatGPT无疑都是AI领域最炙手可热的话题。而它的成功,也引发了行业内外对于对话式AI、LLM模型商业化应用可能性的思考。诚然,尽管就目前来看ChatGPT对大部分问答都能基本做到“对答如流”。但是,ChatGPT本质上依旧是预训…

Flutter Modul集成到IOS项目

Flutter Modul集成到IOS项目中1. 创建一个Flutter Modul2.在既有应用中集成Flutter Modul2.1 Flutter的构建模式选择2.1.1 debug模式2.1.2 Release模式2.1.3 Podfile 模式2.2 Cocoapods管理依赖库集成方式2.3 直接在Xcode中集成framework2.4 Local Network Privacy Permissions…