对象、继承、Symbol

112 阅读3分钟

一、面向对象、面向过程

大象装冰箱

面向过程:更关心的是做事的每个需求的步骤(打开、装、关。完成一个过程):1、2、3、4.

面向对象:大象、冰箱、隐藏对象(更关心的是每一个对象的属性和方法)

js是基于对象的语言、但不全是对象。(类与对象)

类与对象

类:定义同一组对象共有的属性和方法。 

**  **

静态方法中的this指向构造函数。

构造函数中的this指向实例对象

function Person (name, age) {
    // 实例属性
    // 定义共有属性
    console.log(this) // 指向当前实例
    this.name = name
    this.age = age 
    Person.count ++ 
}
// 实例方法:定义共有方法
Person.prototype.say = function () {
    console.log('wo shi' + this.name)
}
// 静态方法
Person.getcount = function () {
    console.log(this) // 静态方法中this执行构造函数Person
    console.log('当前数量' + Person.count)
    console.log(this.name) // 输出undefined
}
// 静态属性
Person.count = 0
var p1 = new Person('hello', 10)
console.log(p1.name)
var p2 = new Person('world', 20)
console.log(p2.name)
p2.say()
Person.count
Person.getcount()

函数继承

构造函数继承
缺点:  构造函数继承只能继承构造函数的属性、不能继承构造函数的方法

function Animal (name) { // 父类定义属性
    this.name = name // this指向实例
}
Animal.prototype.sayName = function () {
    console.log('say +' + this.name)
}
function Dog (name, age) {
    Animal.call(this, name) // 子继承父类的name属性
    this.age = age
} 
var d1 = new Dog('xiaoq', 'red')
console.log(d1.name) //
// d1.sayName() // 报错,构造函数继承,只能继承属性、不能继承方法

原型继承

只能继承原型上的方法和属性、不能继承构造函数内部的属性和方法

function Animal (name) { // 父类定义属性
    this.name = name // this指向实例
}
Animal.prototype.sayName = function () {
    console.log('say +' + this.name)
}
function Dog (name, age) {
    this.age = age
} 
Dog.prototype = new Animal('hello') // * 注意这里
Dog.prototype.constructor = Dog
var d1 = new Dog('xiaoq', 'red')
console.log(d1.name) // hello
d1.sayName() // 

组合继承(构造函数继承和原型继承的组合)

Es6中的类与继承

class\extends\construcor\static\super\get\set

通过get\set属性进行属性拦截。比内部属性操作更加灵活

class Person11 {
    constructor (name,age) { // 定义内部属性
          this.name = name
           this.age = age
            this._sex = -1
    }
    sayName () {
            console.log('say' + this.name)
    }
    // 定义顶层属性
    get sex() { // 属性只可读
        if(this._sex === 1) { 
            return 'male'
         } else if(this._sex === 0){
            return 'female'
        } else {
            return 'no msg'
        }
    }
    set sex(val) { // 设置属性
        if(val === 0 || val === 1) {
            this._sex = val
        }
    }
}
var pp = new Person11('hello', 10)
pp.sex = 10
console.log(pp.sex) // 设置sex属性后获取sex属性
class Children extends Persin11  {
    constructor (name,age,per) {
        super(name, age)
        this.per = per
    }
}
var aa = new Children('hello', 10 , 'world')
console.log(aa.name)
console.log(aa.per)

定义静态方法和静态属性、以及继承
class Person11 {
    constructor (name,age) { // 定义内部属性
          this.name = name
           this.age = age
            this._sex = -1
    }
    sayName () {
            console.log('say' + this.name)
    }
    static getCount () {
        console.log('静态方法')
    }
}
Person11.cuout = 11 // 静态属性
class Children extends Person11  {
    constructor (name,age,per) {
        super(name, age)
        this.per = per
    }
}
var aa = new Children('hello', 10 , 'world')
console.log(aa.name)
Children.getCount()
Person11.getCount()
console.log(Person11.cuout)
console.log(Children.cuout)
// 静态方法和静态属性依然是可以继承的
// static 方式定义静态方法
// 构造名的形式定义静态属性

Symbol (独一无二)

原始数据类型一个有七种。

var s1 = Symbol()
var s2 = Symbol()
console.log(s1 === s2) // false
var s3 = Symbol.for('hello')
var s4 = Symbol.for('hello')
console.log(s3 === s4)

Symbol 和 Symbol.for 的区别

Symbol.for会注入全局、下次定义会去全局中查找,如果定义值一样就会用已有的值

使用场景1

// 一个班级多个同名字的信息展示
var stu1 = '李四'
var stu2 = '李四'
var grade = {
    [stu1]: {address: 'xx', tel: '11'},
    [stu2]: {address: 'yy', tel: '22'}
}
console.log(grade) // 这样的定义得不到相同key值的保存,会被后面的key值覆盖

// 一个班级多个同名字的信息展示
var stu1 =  Symbol('李四')
var stu2 = Symbol('李四')
var grade = {
    [stu1]: {address: 'xx', tel: '11'},
    [stu2]: {address: 'yy', tel: '22'}
}
console.log(grade) //可以保存多个相同的key 值
console.log(grade[stu1])

使用场景2 (对属性的特殊保护)

var sykey = Symbol('hello')

class Users {

    constructor(name,age) {
            this.name = name
            this[sykey] = age
    }
}
var p = new Users('aaa', 10)
console.log(p)
for (var i in p) {
    console.log(i) //拿不到Symbol值
}
for (var i of Object.keys(p)) {
    console.log(i) // 拿不到Symbol值
}
for (var i of Object.getOwnPropertySymbols(p)) {
    console.log(i) // 只能拿到Symbol值
}
for (var i of Reflect.ownKeys(p)) {
    console.log(i) // 可以拿到所有值
}

使用场景3

// 魔术字符串、 只关心key、 不关心value
var shapeType = {
    triangle: Symbol(),
    circle: Symbol()
}
function getArea(shape) {
    let area = 0
    switch(shape) {
           case shapeType.triangle:
                area = 1
                break
            case shapeType.circle:
                area = 2
                break
    }
    return area
}
console.log(getArea(shapeType.triangle))