美文网首页
Class语法

Class语法

作者: bbh123 | 来源:发表于2019-03-15 11:29 被阅读0次

ES6前

function Point(x, y) {//构造函数
  this.x = x;
  this.y = y;
}
Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
//ES6中
class Point {
  constructor(x, y) {//构造函数
    this.x = x;
    this.y = y;
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

class Point {
  // ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true
//对比
class Point {
  constructor() {
    // ...
  }
  toString() {
    // ...
  }
  toValue() {
    // ...
  }
}
// 等同于
Point.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};
//对比
class B {}
let b = new B();
b.constructor === B.prototype.constructor // true
//同时添加多个方法
class Point {
  constructor(){
    // ...
  }
}
Object.assign(Point.prototype, {
  toString(){},
  toValue(){}
});
//ES6内部方法不可枚举
class Point {
  constructor(x, y) {
    // ...
  }
  toString() {
    // ...
  }
}
Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
//constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象。
class Foo {
  constructor() {
    return Object.create(null);
  }
}
new Foo() instanceof Foo
// false

类的实例

//与 ES5 一样,实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
var point = new Point(2, 3);
point.toString() // (2, 3)
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true
//与 ES5 一样,类的所有实例共享一个原型对象。
var p1 = new Point(2,3);
var p2 = new Point(3,2);
p1.__proto__ === p2.__proto__
//true

getter和setter

//存值函数和取值函数是设置在属性的 Descriptor 对象上的。
class CustomHTMLElement {
  constructor(element) {
    this.element = element;
  }
  get html() {
    return this.element.innerHTML;
  }
  set html(value) {
    this.element.innerHTML = value;
  }
}
var descriptor = Object.getOwnPropertyDescriptor(
CustomHTMLElement.prototype, "html"
);
"get" in descriptor  // true
"set" in descriptor  // true

属性表达式

let methodName = 'getArea';
class Square {
  constructor(length) {
    // ...
  }
  [methodName]() {//方法名getArea,是从表达式得到
    // ...
  }
}

Class表达式

const MyClass = class Me {
  getClassName() {
    return Me.name;//类名只能在内部使用
  }
};

// Class 表达式,可以写出立即执行的 Class。
let person = new class {
  constructor(name) {
    this.name = name;
  }
  sayName() {
    console.log(this.name);
  }
}('张三');
person.sayName(); // "张三"

注意点

\\1.类和模块的内部,默认就是严格模式
\\2类没有变量提升hoist
new Foo(); // ReferenceError
class Foo {}
\\3name属性,ES6 的类只是 ES5 的构造函数的一层包装
\\4Generator方法
class Foo {
  constructor(...args) {
    this.args = args;
  }
  * [Symbol.iterator]() {//Generator函数
    for (let arg of this.args) {
      yield arg;
    }
  }
}
for (let x of new Foo('hello', 'world')) {
  console.log(x);
}
// hello
// world
\\5this的指向
class Logger {
  printName(name = 'there') {
    this.print(`Hello ${name}`);//this默认指向Logger类的实例
  }
  print(text) {
    console.log(text);
  }
}
const logger = new Logger();
const { printName } = logger;//this指向该方法运行时所在的环境
printName(); // TypeError: Cannot read property 'print' of undefined
\\解决1绑定this
class Logger {
  constructor() {
    this.printName = this.printName.bind(this);
  }
  // ...
}
\\解决2使用箭头函数
class Logger {
  constructor() {
    this.printName = (name = 'there') => {
      this.print(`Hello ${name}`);
    };
  }
  // ...
}
\\使用Proxy
function selfish (target) {
  const cache = new WeakMap();
  const handler = {
    get (target, key) {
      const value = Reflect.get(target, key);
      if (typeof value !== 'function') {
        return value;
      }
      if (!cache.has(value)) {
        cache.set(value, value.bind(target));
      }
      return cache.get(value);
    }
  };
  const proxy = new Proxy(target, handler);
  return proxy;
}
const logger = selfish(new Logger());

静态方法

class Foo {
  static classMethod() {
    return 'hello';
  }
}
Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
//this指向类
class Foo {
  static bar() {
    this.baz();
  }
  static baz() {
    console.log('hello');
  }
  baz() {//baz方法可重名
    console.log('world');
  }
}
Foo.bar() // hello
//可继承
class Foo {
  static classMethod() {
    return 'hello';
  }
}
class Bar extends Foo {
}
Bar.classMethod() // 'hello'
//super调用
class Foo {
  static classMethod() {
    return 'hello';
  }
}
class Bar extends Foo {
  static classMethod() {
    return super.classMethod() + ', too';
  }
}
Bar.classMethod() // "hello, too"

实例属性新写法

class IncreasingCounter {
  _count = 0;//定义在类顶层
  get value() {
    console.log('Getting the current value!');
    return this._count;
  }
  increment() {
    this._count++;
  }
}

静态属性

// 老写法
class Foo {
  // ...
}
Foo.prop = 1;
// 新写法
class Foo {
  static prop = 1;
}

new.target属性

//构造函数只能通过new命令调用
function Person(name) {
  if (new.target !== undefined) {
    this.name = name;
  } else {
    throw new Error('必须使用 new 命令生成实例');
  }
}
// 另一种写法
function Person(name) {
  if (new.target === Person) {
    this.name = name;
  } else {
    throw new Error('必须使用 new 命令生成实例');
  }
}
var person = new Person('张三'); // 正确
var notAPerson = Person.call(person, '张三');  // 报错
//返回子类
class Shape {
  constructor() {
    if (new.target === Shape) {
      throw new Error('本类不能实例化');
    }
  }
}
class Rectangle extends Shape {
  constructor(length, width) {
    super();
    // ...
  }
}
var x = new Shape();  // 报错
var y = new Rectangle(3, 4);  // 正确

私有方法属性

//方案一
class Widget {
  // 公有方法
  foo (baz) {
    this._bar(baz);
  }
  // 私有方法加下划线_
  _bar(baz) {
    return this.snaf = baz;
  }
  // ...
}
//方案二
//索性将私有方法移出模块
class Widget {
  foo (baz) {
    bar.call(this, baz);
  }
  // ...
}
function bar(baz) {
  return this.snaf = baz;
}
//方案三
const bar = Symbol('bar');
const snaf = Symbol('snaf');
export default class myClass{
  // 公有方法
  foo(baz) {
    this[bar](baz);
  }
  // 私有方法
  [bar](baz) {
    return this[snaf] = baz;
  }
  // ...
};
const inst = new myClass();
Reflect.ownKeys(myClass.prototype)
// [ 'constructor', 'foo', Symbol(bar) ]

相关文章

  • v-bind 及 class 与 style 绑定

    class的绑定 对象语法 数组语法 数组语法中可以使用对象语法 style的绑定 绑定内联样式与绑定class的...

  • Day9:Vue文档精读3——渲染&事件

    class与style的绑定 绑定HTML Class 对象语法 数组语法 用在组件上 绑定内联样式 对象语法 数...

  • Class 与 Style 如何动态绑定?

    Class 与 Style 如何动态绑定? Class 可以通过对象语法和数组语法进行动态绑定: 对象语法: 数组...

  • Class语法

    ES6前 类的实例 getter和setter 属性表达式 Class表达式 注意点 静态方法 实例属性新写法 静...

  • python dict() 函数使用

    dict() 函数用于创建一个字典。 语法 语法: class dict(**kwargs)class dict(...

  • JS原型的面试考点

    class与普通构造函数的区别 class实际上是函数,是语法糖 class在语法上更贴近面向对象的写法。 cla...

  • 第3章 ES6类(Class)使用

    目标 Class基本语法 constructor方法 类的实例对象 1、Class基本语法js传统创建新对象的方法...

  • 第3章 ES6类(Class)使用

    目标 Class基本语法 constructor方法 类的实例对象 1、Class基本语法 js传统创建新对象的方...

  • Vue知识点

    1、class 对象语法 上面的语法表示 active 这个 class 存在与否将取决于数据属性 isActiv...

  • vue.js v-bind绑定class 官方文档提炼

    v-bind绑定class 官方文档提炼 v-bind绑定class有两种语法,1.数组语法2.对象语法;其中 数...

网友评论

      本文标题:Class语法

      本文链接:https://www.haomeiwen.com/subject/atxhmqtx.html