一、面向对象、面向过程
大象装冰箱
面向过程:更关心的是做事的每个需求的步骤(打开、装、关。完成一个过程):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))