# 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)