【JavaScript】MDN 阅读笔记

MDN 阅读笔记

从大一到现在,一直在重度使用 JavaScript 相关的技术栈,却一直也没写过系统的笔记。主要是太熟悉,也因为 JavaScript 确实是一门不需要学习就能直接上手开发的语言。

最近要准备面试,想系统地看看 JS 的语法、特性,觉得是时候记录一些东西了。

这些笔记会忽略一些基础内容,仅记录遇到的问题,以及我认为值得记录的东西。

迭代器协议

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Iterators_and_Generators

可迭代对象(Iterable)具有迭代行为(for of...objyield*([v1, v2]) = obj),这种对象在 this[Symbol.iterator] 下实现了 @@iterator 方法。

@@iterator 方法被要求返回一个对象,该对象应该具有 next() 方法,该方法的返回值标识当前迭代值 value 和迭代状态 done

interface {
  value: T;
  done: boolean;
}

下面的例子是在测试时遇到的一个小坑:

function Collection(iterable) {
  this[Symbol.iterator] = iterable[Symbol.iterator].bind(iterable)
}

const obj = new Collection([1, 2, 3])
for (const item of obj) {
  console.log(item)
}
// out 1 2 3

需要注意的是,在 TS 中,无法直接使用 ES5 风格的 class。

@see https://github.com/microsoft/TypeScript/issues/18171

此外,生成器可以被用作实现 @@iterator 方法,其本身被调用后会返回一个迭代器(具有迭代器协议要求的 next() 方法)。

原型链

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N6NXAao5-1656773283943)(https://gaolihaiimg.oss-cn-beijing.aliyuncs.com/txwlpqbidm)]

function A() { }
function B() { }
B.prototype.__proto__ = A.prototype;
const b = new B();
// assert:
/* 
b.__proto__ === B.prototype;
b.__proto__.__proto__ === A.prototype;
b.__proto__.__proto__.__proto__ === Object.prototype;
b..__proto__.__proto__.__proto__.__proto__ === null;
*/

值得注意的有两个东西,constructorprototype

二者互相引用,即 constructor 下保存了 prototype 的引用,而 prototype 又含有 constructor 的引用。

  • constructor 是实例化 obj 时使用的构造函数。
  • prototype 是 obj 的原型对象。

当我们访问一个实例对象(一般意义上的)的 constructor,实际上访问的是该对象的原型对象上的 constructor 属性,所以会有 obj.__proto__ === obj.constructor.prototype

但不是对所有对象都是这样,例如原型对象本身具有 constructor 属性,不会去它的原型对象上寻找,所以应该仅对实例对象有 obj.__proto__ === obj.constructor.prototype

此外,还要注意的是,正常情况下,原型链(以 __proto__ 连接的)上总是原型对象。

constructor

构造函数也是函数(Function)

function T() {}
T.constructor === Function; // true
实例化

由于原型在构造函数上,所以实例化的行为取决于构造函数。

构造函数不同,导致原型对象(可能)不同,原型链不同。

var obj = new T();
  • 创建一个空对象 obj
  • obj.__proto__ = T.prototype
  • obj.constructor = T
obj.constructor === T // true

this 指向

Browser

globalThis 是一个获取当前环境的顶级对象的标准途径,在 Browser 下,globalThiswindow

当我们在全局作用域下声明的符号(方法和变量),该变量将作为顶级对象的一个属性:

function fn() {
  console.log(this);
}
window.fn(); // window

上例中,我们在全局声明的 fn 方法被放置在了 window 对象下,作为其一个属性。

在函数作用域下声明时,则不会这样。

在我们直接调用方法,而不使用任何对象时:

function fn() {
  console.log(this);
}
fn();
// strict mode: undefined
// default: window

在严格模式下,fn 引用本身不属于任何对象,其内部的 this 指向 undefined

而在非严格模式下,fn 内部的 this 将被替换为当前环境的顶级对象。

这与 call 的行为一致:api:Function.prototype.call

Node.js

Node.js 文件作用域实际上是一个函数作用域:

function Module() {
  this.exports={}
}
function Fun(exports, require,module,__filename,__dirname) {
  // Your code here
}
var module = new Module();
var exports = module.exports;
var options = [exports, require, module, filename, dirname];
Fun.apply(exports,options);

其中的 this 指向 module.exports,这显然与浏览器中的全局作用域并不一样。所以其行为也会有所变化。

例如在文件作用域下声明的变量方法,不会被放置在顶级对象 global 下:

function fn() {
  console.log(this);
}
globalThis.fn(); // error: fn is not a function

此外,其余行为与浏览器下一致。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高厉害

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值