js的this
this 的规则,但是可能会发生多个规则同时出现的情况, 这时 候不同的规则之间会根据优先级最高的来决定 this 最终指向哪里。
-
首先, new 的方式优先级最高,
-
接下来是 bind 这些函数,
-
然后是
-
obj.foo () 这种调用方式,
-
最后是 foo 这种调用方式,
-
同时, 箭头函数的 this ⼀旦被绑定,就不会再被任何方式所改变
js运算符instaneof
instanceof 用于检测一个对象是否是某个构造函数的实例。它的工作原理是检查对象的原型链中是否包含构造函数的 prototype 属性。
具体来说,instanceof 的内部逻辑如下:
- 获取构造函数的 prototype 属性。
- 检查对象的原型链中是否包含该 prototype 对象。
- 如果包含,返回 true;否则返回 false。
注意:基本数据类型(undefined、boolean、number、string、symbol、bigint)在 JavaScript 中是值类型,而不是对象类型。它们没有原型链,因此无法通过 instanceof 来检测
构建函数构建属性
首先先来讲下 class , 其实在 JS 中并不存在类, class 只是语法糖,本质还是函数。
class Person {}
Person instanceof Function // true
function Parent(value) {
this.val = value;
}
Parent.prototype.getValue = function() {
console.log(this.val);
};
const p = new Parent(42);
console.log(p.val); // 输出:42
p.getValue();
构造函数的 constructor 属性 每个对象的原型上都有一个 constructor 属性,它指向创建该对象的构造函数。
- p.constructor 指向 Parent,表示 p 是通过 Parent 构造函数创建的。
- p.proto.constructor 也指向 Parent,因为 p.proto 是 Parent.prototype,而 Parent.prototype.constructor 指向 Parent。
- 注意:Function 是 Object 的子类型,不是构造函数关系,Function.proto==Object.proto
getValue
getValue 方法的作用是为所有通过 Parent 构造函数创建的实例提供一个共享的方法,用于访问或操作实例的属性。它通过原型链机制实现代码复用,节省内存,并封装逻辑。这种机制是 JavaScript 原型继承的核心特性之一。
getValue 方法可以访问实例的属性。在方法内部,this 指向调用该方法的实例,因此可以通过 this 访问实例的属。
js中 call、apply、bind方法
Parent.call(this, value) 是 JavaScript 中实现继承的一种常用方法。它用于在子类的构造函数中调用父类的构造函数,从而将父类的属性和方法传递给子类的实例。这种方法允许子类继承父类的属性和行为
- call 方法用于在特定的上下文中调用一个函数,并传递参数
- apply 方法与 call 类似,但它接受一个参数数组,而不是多个参数
- bind 方法用于创建一个新函数,该函数的 this 值被永久绑定到指定的对象上。bind 不会立即调用函数,而是返回一个新的函数。
- (场景:构造函数里面已经声明了this,但是在构造的实例函数的外部环境中用此this则会丢失指向,所以需要用bind(this)绑定this的指向)
手写call方法
Function.prototype.myCall = function(context) {
if (typeof this !== 'function') {
throw new TypeError( 'Error')
}
context = context || window
context.fn = this
const args = [...arguments].slice(1)
const result = context.fn(...args)
delete context.fn
return result
}
手写apply方法
Function.prototype.myApply = function(context) {
if (typeof this !== 'function') {
throw new TypeError( 'Error')
}
context = context || window
context.fn = this
let result
// 处理参数和 call 有区别
if (arguments [1]) {
result = context.fn(...arguments [1])
} else {
result = context.fn()
}
delete context.fn
return result
}
手写bind方法
Function.prototype.myBind = function (context) {
if (typeof this !== 'function') {
throw new TypeError( 'Error')
}
const _this = this
const args = [...arguments].slice(1)
// 返回⼀个函数
return function F() {
// 因为返回了⼀个函数,我们可以 new F(),所以需要判断
if (this instanceof F) {
26/166
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}
ES Mmodule
ES Module 是原生实现的模块化方案,与 CommonJS 有以下⼏个区别
- CommonJS 支持动态导⼊,也就是 require(${path}/xx.js) ,后者目前不支持,但是 已有提案
- CommonJS 是同步导⼊, 因为用于服务端,文件都在本地, 同步导⼊即使卡住主线程影响 也不大。而后者是异步导⼊, 因为用于浏览器, 需要下载文件, 如果也采用同步导⼊会对 渲染有很大影响
- CommonJS 在导出时都是值拷贝,就算导出的值变了, 导入的值也不会改变,所以如果想 更新值,必须重新导入⼀次。但是 ES Module 采用实时绑定的方式, 导入导出的值都指 向同⼀个内存地址,所以导入值会跟随导出值变化
- ES Module 会编译成 require/exports 来执行的
Node Eventloop
Node 中的Eventloop Node 中的 Event loop 和浏览器中的不相同。 Node 的 Event loop 分为 6 个阶段, 它们会按照顺序反复运行
冒泡排序
自定义属性
- html5中推出专门的data-自定义属性
- 在标签上一律以data-开头
- 在DOM对象上一律以dataset对象方式获取