# 202107

# class 继承

  • super指向父类的原型对象,所以定义在父类实例上的方法和属性,是无法通过super调用的。
  • 如果属性定义在父类的原型对象上,super就可以取到
  • es6 规定,在子类普通方法中通过super调用父类的方法时,方法内部的this指向当前的子类实例
  • super 在静态方法之中指向父类,在普通方法之中指向父类的原型对象

# ES6 class

1、class 创建的内部定义的方法是不可枚举的 2、可以通过实例的__proto__属性为“类”添加方法。

proto 并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但依旧不建议在生产中使用该属性,避免对环境产生依赖。生产环境中,我们可以使用 Object.getPrototypeOf 方法来获取实例对象的原型,然后再来为原型添加方法/属性。

var p1 = new Point(2,3)
var p2 = new Point(3,2)

p1.__proto__.printName = function () { return 'Oops' }

p1.printName() // "Oops"
p2.printName() // "Oops"

var p3 = new Point(4,2)
p3.printName() // "Oops"

上面代码在p1的原型上添加了一个printName()方法,由于p1的原型就是p2的原型,因此p2也可以调用这个方法。而且,此后新建的实例p3也可以调用这个方法。这意味着,使用实例的__proto__属性改写原型,必须相当谨慎,不推荐使用,因为这会改变“类”的原始定义,影响到所有实例。

class Point {
    toValue(){}
}

Object.assign(Point.prototype, {
    toString(){
        console.log('toSting')
    },
    
})

console.log(Object.keys(Point.prototype)) // ['toString']

3、Class 表达式可以写出立即执行的Class

##在javascript中创建对象的可行方法有哪些

1、对象构造函数

var object = new Object()

2、对象的创建方法

var object = Object.create(null)

3、对象字面量语法

var object = {}

4、函数构造器

function Person(name) {
  var object = {}
  object.name = name
  object.age = 21
  return object
}
var object = new Person('sanp')

5、带有原型的函数构造函数

// 这类似于函数构造函数,但它使用原型作为其属性和方法
function Person(){}
Person.prototype.name = 'sanplee'
var object = new Person()
// 等效于 使用具有函数原型的对象创建的实例,然而使用实例和参数作为参数调用该函数

function func(){}
new func(x, y, z)

// (或者)
//使用函数原型创建一个新实例
var newInstance = Object.create(func.prototype)
//调用函数
var result = func.call(newInstance, x, y, x)

6、es6类语法

class Person {
  constructor(name) {
    this.name = name
  }
}
var object = new Person('cailiao')

7、单例模式

// singleton 是一个只能实例化一次的对象。对其构造函数的重复调用返回相同的实例,这样可以确保他们不会意外创建多个实例

var object = new function() {
  this.name = 'caoliao'
}

8、new是从构造函数生成实例对象的命令

# 什么是原型链

原型链用于基于现有对象构建新类型的对象。它类似于基于类的语言中的继承

对象实例上的原型可以通过Object.getPrototypeOf(object)或proto属性获得,而构造函数带上的原型可用过Object.prototype获得

# call、apply、bind有什么区别

call()方法调用一个函数,给定的this值和参数一一提供

var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};

function invite (greeting1, greeting2) {
  console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}
invite.call(employee1, 'Hello', 'How are you?')

apply()调用具有给定this值的函数,并允许你将参数作为数据传入

var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};

function invite (greeting1, greeting2) {
  console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}
invite.apply(employee1, ['Hello', 'How are you?'])

bing()返回一个新函数,允许你传递任意数量的参数

var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};

function invite (greeting1, greeting2) {
  console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}

var inviteEmployee = invite.bind(employee1)

inviteEmployee1('Hello', 'How are you?'); 

call和apply可以互换。两者都立即执行当前函数。你需要决定是发送数组还是逗号分隔的参数列表更容易。你可以通过call用于(分隔列表)和appley用于array来记住。

而bind创建一个新函数,该函数将this设置为传递给bind的第一个参数

# es6中的类是什么

在es6中,javascript 类主要是对JavaScript现有的基于原型的继承的语法糖

//基于原型继承
function Bike (model, color) {
  this.model = model
  this.color = color
}

Bike.prototype.getDetail = function () {
  return this.model + ' bike has' + this.color + ' color';
}

//es6类
class Bike {
  constructor (model, color) {
    this.model = model
    this.color = color
  }
  getDetail() {
    return this.model + ' bike has' + this.color + ' color';
  }
}

# bind() 方法

bind()将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值

例如:f.bind(obj),实际上可以理解为obj.f(),这时f函数体内的this指向的是obj

var a = {
  b: function () {
    var func = function () {
        console.log(this.c)
    }
    func()
  },
  c: 'hello'
}

a.b() // undefined  这里的this指向的全局作用域,所以返回undefined
var a = {
  b: function () {
    var that = this //可以通过赋值的方式将this赋值给that
    var func = function () {
        console.log(that.c)
    }
    func()
  },
  c: 'hello'
}

a.b() // hello  
var a = {
  b: function () {
    var func = function () {
        console.log(this.c)
    }
    func.bind(this)()
  },
  c: 'hello'
}

a.b()

# slice 内部实现

Array.prototype.slice = function (start, end) {
  var result = new Array()
  var start = start || 0
  var end = end || this.length
  for(var i= start; i < end; i++){
    result.push(this[i])
  }
  return result
}

# vue 视频记录

  • 组件上的事件监听其实是子组件自己在监听,也就是说谁触发谁监听

# 手动实现instanceof的功能

function myInstanceof(left, right){
  //基本数据类型返回false
  if(typeof left !== 'object' || left === null) return false

  //getPrototypeOf 是Object对象自带的一个方法,能够拿到参数的原型对象
  let proto = Object.getPrototypeOf(left)
  while (true){
    // 查到尽头,还没查到
    if(proto == null) return false

    //找到相同的原型对象
    if (proto == right.prototype) return true

    proto = Object.getPrototypeOf(proto)
  }
}

# js 如何实现继承

1、借助call

// 盗用构造函数
function SuperType(name) {
  this.name = name
}

function SubType () {
  //继承SuperType 并传参
  SuperType.call(this, 'sanplee')
  this.age = '35'
}
var instance = new SubType()

这样写的时候子类虽然能够难道父类的属性值,但是问题是父类原型对象中一旦存在方法那么子类无法继承

2、借助原型链

function SuperType(name) {
  this.name = 'parent'
}

function SubType () {
  this.type = 'child'
}

SubType.prototype = new SuperType()

console.log(new SubType())

3、将前两种组合(组合继承)

function SuperType(name) {
  this.name = name
  this.colors = ['red', 'blue', 'green']
}

SuperType.prototype.sayName = function () {
  console.log(this.name)
}

function SubType (name, age) {
  //继承属性
  SuperType.call(this, name)
  this.age = age
}

//继承方法
SubType.prototype = new SuperType()
SubType.prototype.sayAge = function(){
  console.log(this.age)
}

let instanceof1 = new SubType('Sanplee', 29)
instanceof1.colors.push('black')
console.log(instanceof1.colors)
instanceof1.sayName()
instanceof1.sayAge()

let instanceof2 = new SubType('Hanhaoniao', 35)

console.log(instanceof2.colors)
instanceof2.sayName()
instanceof2.sayAge()

# 模拟实现一个new的效果

/**
 *
 * new 被调用后做了三件事
 * 1、让实例可以访问到私有属性
 * 2、让实例可以访问构造函数原型(constructor.prototype)所在原型链上的属性
 * 3、如果构造函数返回的结果不是引用类型
 */

function newOp(ctor, ...args) {
  if(typeof ctor !== 'function') {
    throw 'newOp function this first param must be a function'
  }
  let obj = Object.create(ctor.prototype)
  let res = ctor.apply(obj, args)
  let isObject = typeof  res === 'object' && res !== null
  let isfunction = typeof res === 'function'
  return isObject || isfunction ? res : obj
}

# WeakSet

1、WeakSet里面的引用,都不计入垃圾回收机制,所以不存在内存泄漏 2、WeakSet可以接受一个数组或者类似数组的对象作为参数 3、WeakSet没有size属性,没有办法遍历它的成员

# 冒泡排序算法

var arr = [1,3,2,5,6,8,9,7,4]

for(var i = 0; i< arr.length -1; i++){
  for(var j=0; j < arr.length - 1 - i; j++ ){
    if(arr[j] > arr[j + 1]){
      const temp = arr[j + 1]
      arr[j+1] = arr[j]
      arr[j] = temp
    }
  }
}

console.log(arr)
Last Updated: 7/19/2021, 5:31:30 PM