转载:https://juejin.cn/post/7098891689955164168

ECMAScript 6 提供了更接近传统语言的写法,新引入的class关键字具有正式定义类的能力。类(class)是ECMAScript中新的基础性语法糖结构,虽然ECMAScript 6类表面上看起来可以支持正式的面向对象编程,但实际上它背后使用的仍然是原型和构造函数的概念,让对象原型的写法更加清晰、更像面向对象编程的语法。

一、类的定义

定义类也有两种主要方式:类声明和类表达式。这两种方式都使用class关键字加大括号:

 

kotlin

代码解读
复制代码
// 类声明
class Person {} // 类表达式
const TestPerson = class {}

注意:函数声明类声明之间的一个重要区别在于,函数声明会提升,类声明不会。需要先声明类,然后再访问它,否则就会出现ReferenceError,如:

 

arduino

代码解读
复制代码
const test = new Person(); // ReferenceError: Person is not defined

class Person {}

另一个跟函数声明不同的地方是,函数受函数作用域限制,而类受块作用域限制:

 

javascript

代码解读
复制代码
{
   function FunctionDeclaration () {}
   class ClassDeclaration {}
   // 使用var 声明
   var VarClass = class {}
   // 使用let/const 声明
   let LetClass = class {}
} console.log(FunctionDeclaration) // FunctionDeclaration () {}
console.log(ClassDeclaration) // ReferenceError: ClassDeclaration is not defined
console.log(VarClass) // class {}
console.log(LetClass) // ReferenceError: letClass is not defined

class 类完全可以看成构造函数的另一种写法,这种写法可以让对象的原型属性和函数更加清晰。

 

javascript

代码解读
复制代码
class Person {}

console.log(typeof Person) // function
console.log(Person === Person.prototype.constructor) // true

上面代码表明,类的数据类型就是函数,类本身就指向构造函数。

二、类构造函数

constructor 方法是一个特殊的方法,这种方法用于创建和初始化一个由class创建的对象。通过 new 关键字生成对象实例时,自动会调用该方法。一个类只能拥有一个名为constructor构造函数,不能出现多个,如果定义了多个constructor构造函数,则将抛出 一个SyntaxError错误。如果没有定义constructor构造函数,class 会默认添加一个空的constructor构造函数。

 

kotlin

代码解读
复制代码
class Person {}

// 等于

class Person {
   constructor () {}
}

使用new操作符实例化Person的操作等于使用new调用其构造函数。唯一可感知的不同之处就是,JavaScript解释器知道使用new和类意味着应该使用constructor函数进行实例化。

类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。

 

scss

代码解读
复制代码
class Person {}

Person() // TypeError: Class constructor Test1 cannot be invoked without 'new'

使用new调用类的构造函数会执行如下操作。

  1. 在内存中创建一个新对象;
  2. 这个新对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性;
  3. 构造函数内部的this被赋值为这个新对象(即this指向新对象);
  4. 执行构造函数内部的代码(给新对象添加属性);
  5. 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象;

一起来看看下面例子:

 

javascript

代码解读
复制代码
class Person {}

class Test1 {
   constructor () {
       console.log('Test1 初始化')
  }
} class Test2 {
   constructor () {
       this.test = '通过初始化构造函数设置值'
  }
} // 构造函数返回指定对象
const dataObj = { n: '自定义实例对象' }
class Test3 {
   constructor () {
       this.test = '通过初始化构造函数设置值'
       return dataObj
  }
} const a = new Person();
const b = new Test1(); // Test1 初始化
const c = new Test2();
console.log(c.test) // 通过初始化构造函数设置值 const d = new Test3();
d instanceof Test3; // false
console.log(d) // { n: '自定义实例对象' }

类实例化时传入的参数会用作构造函数的参数。如果不需要参数,则类名后面的括号也是可选的:

 

javascript

代码解读
复制代码
class Person {
   constructor (...args) {
       console.log(args.length)
  }
} class Test1 {
   constructor (test) {
       console.log(arguments.length)
       this.test = test || '默认值'
  }
} // 不传值 可以省略()
const a = new Person // 0
const b = new Person('1', '2') // 2 const c = new Test1() // 0
console.log(c.test) // 默认值 const d = new Test1('传入值') // 1
console.log(d.test) // 传入值 const d = new Test1('1', '2', '3') // 3
console.log(d.test) // 1

与立即调用函数表达式相似,类也可以立即实例化:

 

arduino

代码解读
复制代码
const a = new class Person {
   constructor (text) {
       this.text = text
       console.log(text)
  }
}('立即实例化类'); // 立即实例化类 console.log(a); // Person

三、类的实例 、原型及类成员

类的语法可以非常方便地定义应该存在于实例上的成员、应该存在于原型上的成员,以及应该存在于类本身的成员。

实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上。

每个实例都对应一个唯一的成员对象,这意味着所有成员都不会在原型上共享:

 

javascript

代码解读
复制代码
class Person {
   constructor (x, y) {
       this.text = new Number(1);
       this.x = x
       this.y = y
       this.getText = () => {console.log(this.text)}
  }    toString () {
       console.log(`${this.x}, ${this.y}`)
  }
} const test1 = new Person('x', 'y'), test2 = new Person('x2', 'y2'); console.log(test1.getText()) // Number {1}
console.log(test2.getText()) // Number {1}
console.log(test1.x, test1.y) // x y
console.log(test2.x, test2.y) // x2 y2 // console.log(test1.text === test2.text) // false
// console.log(test1.getText === test2.getText) // false test1.text = '测试' console.log(test1.getText()) // 测试
console.log(test2.getText()) // Number {1} test1.toString() // x, y
test2.toString() // x2, y2 test1.hasOwnProperty('x'); // true
test1.hasOwnProperty('y'); // true
test1.hasOwnProperty('getText'); // true
test1.hasOwnProperty('toString'); // false
test1.__proto__.hasOwnProperty('toString'); // true // 类的实例共享同一个原型对象
console.log(test1.__proto__ === test2.__proto__) // true // 也可以使用ES6提供的 Object.getPrototypeOf 来获取prototype
const test1Prototype = Object.getPrototypeOf(test1)
test1Prototype.myName = '共享字段' // test2 中也是能获取到
console.log(test2.myName) // 共享字段

x、y、text和getText都是实例对象test1自身的属性,所以hasOwnProperty()方法返回true,而toString()是原型对象的属性(因为定义在Person类),所以hasOwnProperty()方法返回false,这些都与 ES5 的行为保持一致。

类的所有实例共享同一个原型对象。这也意味着,可以通过实例的__proto__属性或Object.getPrototypeOf方法获取原型为“类”添加方法,这将会出现共享情况,必须相当谨慎,不推荐使用,因为这会改变“类”的原始定义,影响到所有实例。

类方法等同于对象属性,因此可以使用字符串、符号或计算的值作为键:

 

scss

代码解读
复制代码
const symbolKey = Symbol('test')

class Person {
   stringKey () {
       console.log('stringKey')
  }   [symbolKey] () {
       console.log('symbolKey')
  }   ['calculation' + '1'] () {
       console.log('calculation')
  }
} const a = new Person(); a.stringKey() // stringKey
a[symbolKey]() // symbolKey
a.calculation1() // calculation

getter 与 setter

在 class 内部可以使用 get 与 set 关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。

 

kotlin

代码解读
复制代码
class Person {
   constructor (test) {
       this.test = test || '默认值'
  }    get prop () {
       return this.test
  }    set prop (value) {
       console.log(`setter prop value: ${value}`)
       this.test = value
  }
} const p = new Person('1') p.prop // 1 p.prop = '2' // setter prop value: 2 p.prop // 2

set函数和get函数是设置在属性的 Descriptor 对象上的,可以通过 Object.getOwnPrototyDescriptor 来获取指定属性的指定描述对象。

 

javascript

代码解读
复制代码
const descriptor = Object.getOwnPropertyDescriptor(Person.prototype, 'prop')

'get' in descriptor // true
'set' in descriptor // true

Generator 方法

如果某个方法之前加上星号(*),就表示该方法是一个 Generator 函数:

 

scss

代码解读
复制代码
class Person {
constructor(...args) {
  this.args = args;
}
* generatorFun () {
  for (let arg of this.args) {
    yield arg;
  }
}
} const a = new Person(1,2,3,4);
const generatorNext = a.generatorFun().next
generatorNext() // {value: 1, done: false}
generatorNext() // {value: 2, done: false}
generatorNext() // {value: 3, done: false}
generatorNext() // {value: 4, done: false}
generatorNext() // {value: undefined, done: true}

this 指向

类的方法内部如果含有this,它默认指向类的实例。但是某些情况是指向当前执行环境;

 

arduino

代码解读
复制代码
class Person {
   constructor () {
       this.text = '1'
  }    getText () {
       console.log(this.text)
  }
} const a = new Person() a.getText() // 1 const {getText} = a // this 指向为undefined class 默认严格模式
getText() // TypeError: Cannot read properties of undefined (reading 'text')

上面找不到 this 问题,this会指向该方法运行时所在的环境,因为 class 内部是严格模式,所以 this 实际指向的是undefined。有两个方法解决当前问题:

第一、构造方法中绑定this:

 

kotlin

代码解读
复制代码
class Person {
   constructor() {
       this.text = '1'
       this.getText = this.getText.bind(this)
  }    getText () {
       console.log(this.text)
  }
}

第二、使用箭头函数:

 

javascript

代码解读
复制代码
class Person {
   constructor() {
       this.text = '1'
  }    getText = () => {
       console.log(this.text)
  }
}

箭头函数内部的 this总是指向定义时所在的对象。

第三、使用proxy 在获取方法的时候自动绑定this:

 

kotlin

代码解读
复制代码
function classProxy (target) {
   const map = new Map()
   
   // 读取拦截配置, 只需要配置 get
   const hanlder = {
       get(target, key) {
           const val = Reflect.get(target, key)
           // 要获取的是函数执行, 如果不是函数就直接返回 val
           if (typeof val !== 'function') return val            if (!map.has(val)) {
               // 使用 bind改变运行函数的 this为拦截的实例对象
               map.set(val, val.bind(target))
          }
           return map.get(val)
      }
  }
   const proxy = new Proxy(target, hanlder)
   return proxy
} class Person {
   constructor (text) {
       this.text = text
  }    getText () {
       console.log(this.text)
       return this.text
  }
} const person = classProxy(new Person('test')) const { getText } = person getText() // test

四、静态方法、静态属性及静态代码块

静态方法、静态属性及静态代码块(proposal-class-static-block)都是使用 static关键字定义的属性、方法或块只能 class 自己用,不能通过实例继承。

静态方法中的this 指向的是 当前类,而不是指向实例对象。静态属性是当前类自身的属性。

 

javascript

代码解读
复制代码
class Person {
   static staticProp = 'Person静态属性'    constructor () {
       // 通过 类名 获取
       console.log(`output: ${Person.staticProp}`)        // 也可以通过 构造函数的属性
       this.constructor.staticFun1()
  }    static staticFun1 () {
       this.staticFun2()
       console.log(`output: 静态方法staticFun1,获取Person静态属性 ==> ${Person.staticProp}`)
  }    static staticFun2 () {
       console.log(`output: 静态方法staticFun2,获取静态属性 ==> ${this.staticProp}`)
  }
} Person.staticProp // 静态属性 Person.staticFun1()
// output: 静态方法staticFun2,获取静态属性 Person静态属性
// output: 静态方法staticFun1,获取Person静态属性 ==> Person静态属性 const a = new Person() // output: Person静态属性
a.staticProp // undefined
a.staticFun1 // undefined
a.staticFun2 // undefined
// 通过其原型构造函数还是能获取到 这些静态属性及方法 不推荐使用
// a.__proto__.constructor.staticProp
// a.__proto__.constructor.staticFun1()

静态代码块:

是在 Class 内创建了一个块状作用域,这个作用域内拥有访问 Class 内部私有变量的特权,在这个代码块内部,可以通过 this 访问 Class 所有成员变量,包括 # 私有变量,且这个块状作用域仅在引擎调用时初始化执行一次 ,决解以前初始化静态类属性需要设置一个静态变量初始化逻辑。

注意: static 变量或代码块都按顺序执行,父类优先执行,一个类中允许多个静态代码块存在。

 

kotlin

代码解读
复制代码
class Person {
   static staticProp = '静态属性'
   static staticPropArr = []
   static staticPropObj = {}
   
   static getStatic (name) {
       console.log(`获取:${name}`, name && this[name])
       return name && this[name]
  }    static resetData (name, data) {
       name && (this[name] = data)
       console.log(`重置:${name}`, name && this[name])
  }    static {
       console.log('静态代码块执行');
       this.getStatic('staticProp');
       this.getStatic('staticPropArr');
       this.getStatic('staticPropObj');        this.resetData('staticProp', '重置静态属性');
       this.resetData('staticPropArr', ['重置静态数组']);
       this.resetData('staticPropObj', { text: '重置静态对象' });        this.staticPropObj.staticBlock1 = '代码块中直接设置'
       console.log(this.staticPropObj)
  }
} /**
* 静态代码块执行
获取:staticProp 静态属性
获取:staticPropArr []
获取:staticPropObj {}
重置:staticProp 重置静态属性
重置:staticPropArr ['重置静态数组']
重置:staticPropObj {text: '重置静态对象'}
{text: '重置静态对象', staticBlock1: '代码块中直接设置'}
*/

上面代码中可以看出,static 关键字后面不跟变量,而是直接跟一个代码块,就是 class static block 语法的特征,在这个代码块内部,可以通过 this 访问 Class 所有成员变量,包括 # 私有变量。

在这里提前使用一下私有变量,理论上 class 私有变量外部是访问不了的,但是有了静态代码块( *class-static-block *)之后,我们可以将私有属性暴露给外部变量:

 

javascript

代码解读
复制代码
let privateValue

export class Person {
 #value
 constructor(x) {
   this.#value = x
}  static {
   privateValue = (obj) => obj.#x;
}
} export function getPrivateValue (obj) {
 return privateValue(obj)
} // 在另一个文件中
import { Person, getPrivateValue } from 'xxx' const a = new Person('私有变量') getPrivateValue(a) // 私有变量

其实class-static-block本质上并没有增加新功能,我们完全可以用普通静态变量代替,只是写起来很不自然,所以这个特性可以理解为对缺陷的补充,或者是语法完善,个人认为现在越来越像java。

五、私有属性和私有方法

私有属性和私有方法,是只能在类的内部访问的方法和属性,外部不能访问,不可以直接通过 Class 实例来引用,其定义方式只需要在方法或属性前面添加#

私有属性:

 

arduino

代码解读
复制代码
class Person {
   #privateVar1;
   #privateVar2 = '默认值';
   
   constructor (text) {
       this.#privateVar1 = text || '--'
       console.log(this.#privateVar1)
  }    getPrivateData1 (key) {
       // 这里是获取不了的
       console.log('传入key来获取私有变量:', this[key])
       console.log('获取私有变量', this.#privateVar2, this.#privateVar1)
  }    static staticGetPrivateData (person, key) {
       console.log('静态方法获取私有变量:', person.#privateVar2, person.#privateVar1)                    
       // 下面是获取不到
       console.log('静态方法传入key来获取私有变量:', person[key])
  }
} const a = new Person() // 不传 默认 --
// output: -- a.getPrivateData1('#privateVar1')
// output: 传入key来获取私有变量:undefined
// output: 获取私有变量: 默认值 -- // 使用静态方法
Person.staticGetPrivateData(a, '#privateVar1')
// output: 静态方法获取私有变量: 默认值 --
// output: 静态方法传入key来获取私有变量:undefined

从上面代码中我们可以看到,私有变量是只能内部读取或写入,不能通过动态key读取(外部调用就会报错)

注意:在class 中 公共属性 test 与 #test 是两个完全不同的值;

私有方法:

 

arduino

代码解读
复制代码
class Person {
   #private;
   
   constructor () {
       this.#private = '私有变量'
       this.#methods() // 调用私有方法
  }    #methods () {
       console.log('私有方法#methods:', this.#private)
  }    static #staticMethods (person) {
       if (person) {
           console.log('静态私有方法#staticMethods person获取值', person.#private)
           person.#methods()
      }
  }    init1 () {
       this.#methods()
       console.log('使用this')
       Person.#staticMethods(this)
  }    init2 (person) {
       if (person) {
           console.log('使用传入实例')
           Person.#staticMethods(person)
      }
     
  }
} const a = new Person()
// output: 私有方法#methods: 私有变量 // a.#methods() SyntaxError
// a['#methods']() TypeError: a.#methods is not a function a.init1()
// output: 私有方法#methods: 私有变量
// output: 使用this
// output: 静态私有方法#staticMethods person获取值 私有变量
// output: 私有方法#methods: 私有变量 a.init2(a)
// output: 使用传入实例
// output: 静态私有方法#staticMethods person获取值 私有变量
// output: 私有方法#methods: 私有变量

从上面代码中我们可以看到,私有方法只能内部调用,在外部调用就会报错。

六、继承 extends

使用 extends 关键字,让子类继承父类的属性和方法。

 

javascript

代码解读
复制代码
class Person {
   num = 1
   text = 'person'    getNum = () => console.log(this.num, this)    addNum () {
       console.log(++this.num, this)
  }
} // 继承
class Child extends Person {
   constructor () {
       super()
       this.getText()
  }    getText = () => console.log(this.text, this)
} const a = new Child() // output: person Child {} console.log(a instanceof Child) // output: true
console.log(a instanceof Person) // output: true a.getText() // output: person Child {}
a.getNum() // output: 1 Child {}
a.addNum() // output: 2 Child {}
a.getNum() // output: 2 Child {} a.text // person
a.num // 2

从上面代码中,我们可以看出Child 类 继承了 Person 的属性及方法,在Child 中也是可以调用Person的方法及属性,注意 this 的值会反映调用相应方法的实例或者类。子类中(Child)如果设置了 constructor 方法 就必须调用 super() ,否则就会出现新建实例时报错,如果没有 constructor 构造函数,在实例化继承类时会调用 super() ,而且会传入所有传给继承类的参数(后面会详细讲解)。

 

arduino

代码解读
复制代码
class Person {
   static staticText = 'staticText';
   #private = 'private'    static staticMethods1 (person) {
       console.log('staticMethods1', this)
       person.#privateMethods()
  }    #privateMethods () {
       console.log('#privateMethods', this)
  }
} // 使用表达式格式 也是可以使用 extends 继承
const Child = class extends Person {
   methods () {
       console.log('methods', Child.staticText)
  }
} const a = new Child() a.methods() // output: methods staticText Child.staticMethods1(a)
// output: staticMethods1 class Child {}
// output: #privateMethods Child {} Person.staticMethods1(a)
// output: staticMethods1 class Person {}
// output: #privateMethods Child {}

使用表达式格式 也是可以使用 extends 继承,类 的静态方法与属性是可以继承的,其私有属性及方法是不能继承的,可以从继承的共有方法与静态方法 中获取其私有属性或调用其私有方法。

super 关键字可以作函数使用,也可以作对象使用,但是其只能在继承类中使用,且只能在继承类的constructor 构造函数、实例方法和静态方法中使用。作为函数时是在 继承类的constructor 构造函数中使用,根据要求如果继承类中定义了constructor构造函数就必须要调用super方法(调用父类的constructor),否则就会报错。

 

scala

代码解读
复制代码
class Person {}

class Child extends Person {
  constructor () {
      // 如果不调用 super() 就会报错
      // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor  
      super() // 调用父级的constructor
      console.log(this) // Child {}  
  }
}

注意: constructor() 中必须super() 顶部首段执行代码,否则也是一样报错;

在使用 super() 时应该注意下面几个问题:

  1. super只能在继承类构造函数和静态方法中使用。

     

    javascript

    代码解读
    复制代码
    class Person {
       constructor () {
           // 在非继承类 的constructor 中使用super 会报错
           super() // SyntaxError: 'super' keyword unexpected here
      }    methods () {
           console.log(super.text) // undefined
      }    static staticMethods () {
           console.log(super.text) // undefined
      }
    }
  2. 不能单独引用super关键字,要么用它调用构造函数,要么用它引用静态方法。

     

    scala

    代码解读
    复制代码
    class Person {}
    
    class Child extends Person {
       
       constructor () {
           super // SyntaxError: 'super' keyword unexpected here
      }    methods () {
           console.log(super) // SyntaxError: 'super' keyword unexpected here
      }    static staticMethods () {
           console.log(super) // SyntaxError: 'super' keyword unexpected here
      }
    }
  3. 调用super()会调用父类构造函数,并将返回的实例赋值给this

     

    scala

    代码解读
    复制代码
    class Person {}
    class Child extends Person {
       constructor () {
           super()
           console.log(this instanceof Person) // output: true
      }
    } new Child()
  4. super() 的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入。

     

    scala

    代码解读
    复制代码
    class Person {
       constructor (text) {
           this.text = text
      }
    } class Child extends Person {
       constructor (text) {
           super(text)
      }
    } // 这里注意 其text 会设置到Child 中
    const a = new Child('设置 text') // Child { text: '设置 text' } console.log(a.text) // output: 设置 text
  5. 如果没有定义类构造函数,在实例化继承类时会调用super(),而且会传入所有传给继承类的参数。

     

    scala

    代码解读
    复制代码
    class Person {
       constructor (text) {
           this.text = text
      }
    } class Child extends Person {} const a = new Child('设置 text'); // Child { text: '设置 text' } // 上面提到过 会默认 生成 constructor (...arge) {super(...arge)}
  6. 在类构造函数中,不能在调用super()之前引用this,文章上面已经有案例及说明。

  7. 如果在继承类中显式定义了构造函数,则要么必须在其中调用super(),要么必须在其中返回一个对象。

     

    scala

    代码解读
    复制代码
    class Person {
       methods () {}
    } class Child1 extends Person {} class Child2 extends Person {
       constructor () {
           super()
      }
    } class Child3 extends Person {
       constructor () {
           return {}
      }
    } const a = new Child1() // Child1 {} const b = new Child2() // Child2 {} const c = new Child3() // {} 指向 实例函数 返回的对象

    关于JS Class 相关就介绍到这里

 

JS之Class类的更多相关文章

  1. js常用工具类.

    一些js的工具类 复制代码 /** * Created by sevennight on 15-1-31. * js常用工具类 */ /** * 方法作用:[格式化时间] * 使用方法 * 示例: * ...

  2. 通过寄生组合式继承创建js的异常类

    最近项目中在做js的统一的异常处理,需要自定义异常类.理想的设计方案为:自定义一个异常错误类BaseError,继承自Error,然后再自定义若干个系统异常,例如用户取消异常.表单异常.网络异常,这些 ...

  3. JS中定义类的方法

    JS中定义类的方式有很多种: 1.工厂方式    function Car(){     var ocar = new Object;     ocar.color = "blue" ...

  4. js模块,类,继承,命名空间,私有属性等相关概念梳理

    js确切的说是一种基于对象的语言,和纯面向对象的语言(比如as)稍微有点区别,js中没有类的概念.虽然有继承但是基于原型的继承.随着前段越来越受重视,jser们利用js的一些特性他们制造出了和纯面向对 ...

  5. JS中定义类的方法<转>

    转载地址:http://blog.csdn.net/sdlfx/article/details/1842218 PS(个人理解): 1) 类通过prototype定义的成员(方法或属性),是每个类对象 ...

  6. js集合set类的实现

    js集合set类的实现 /*js集合set类的实现*/ function Set() { this.dataStore = []; this.add = add;//新增元素 this.remove ...

  7. 使用js栈stack类的实现

    使用js栈stack类的实现 /*使用栈stack类的实现*/ function stack() { this.dataStore = [];//保存栈内元素,初始化为一个空数组 this.top = ...

  8. js中的类和对象以及自定义对象

    js中的类 1.类的声明 function Person(name,age){ this.name=name; this.age=age; this.test=function(a){ alert(a ...

  9. js中尺寸类样式

    js中尺寸类样式 一:鼠标尺寸类样式 都要事件对象的配合 Tip:注意与浏览器及元素尺寸分开,鼠标类尺寸样式都是X,Y,浏览器及元素的各项尺寸时Height,Width 1:检测相对于浏览器的位置:e ...

  10. koa 基础(十七)原生 JS 中的类、静态方法、继承

    1.app.js /** * 原生 JS 中的类.静态方法.继承 * es5中的类和静态方法 */ function Person(name, age) { // 构造函数里面的方法和属性 this. ...

随机推荐

  1. Java 1.8 Stream流原理与用法总结

    一.接口设计 从Java1.8开始提出了Stream流的概念,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式:依旧先看核心接口的设计: BaseStream:基础接口,声明了流管理的核心 ...

  2. C++:使自定义类支持迭代器

    概述 在 C++ 中,链表迭代器是一种用来遍历链表(如 std::list)元素的工具.链表是一种数据结构,其中每个元素(节点)包含一个数据值和一个指向下一个节点的指针.链表迭代器允许以类似于数组的方 ...

  3. ASP.NET Core – ADO.NET

    前言 自从用 Entity Framework 就再也没有用过 ADO.NET 了. 很多年前写过 基础 ADO.NET 访问MYSQL 与 MSSQL 数据库例子. 今天刚好想做个单侧, 那就顺便翻 ...

  4. Yarn 3.0 Plug'n'Play (PnP) 安装和迁移

    前言 以前用 npm, 后来 yarn 火了就用 yarn. 后来 yarn 2.0 大改版, Angular 不支持就一直没用. 一直到去年的 Angular 13 才开始支持. 最近又开始写 An ...

  5. ASP.NET Core – 读写 Request / Response

    需求 常见的需求就是从 request 里面读取一些 information. 比如 request URL, header, cookie, 写入 response header, cookie 实 ...

  6. POJ-2229 Sumsets(基础dp)

    Farmer John commanded his cows to search for different sets of numbers that sum to a given number. T ...

  7. 26岁女生转行车载测试1年,月入15K~

    年前有朋友找工作,跟我说简历改了车载后,收到的打招呼翻了几倍,如今车载测试前景非常广阔,因为越来越多的汽车厂商正在开发新的可智能化的汽车,他们需要测试这些汽车的性能,安全性以及可靠性.车载测试技术可以 ...

  8. 2024年常用的Net web框架

    ASP.NET Core 框架声明:是微软推出的新一代开源.跨平台的 Web 应用框架,用于构建高性能.现代化的 Web 应用程序. 官网地址:https://dotnet.microsoft.com ...

  9. 《Vue.js 设计与实现》读书笔记 - 第12章、组件的实现原理

    第12章.组件的实现原理 12.1 渲染组件 在渲染器内部的实现看,一个组件是一个特殊类型的虚拟 DOM 节点.之前在 patch 我们判断了 VNode 的 type 值来处理,现在来处理类型为对象 ...

  10. php生成验证码类

    php生成验证码类 直接看代码 <?php session_start(); class Code{ //资源 private $img; //画布宽度 private $width=100; ...