119. 面试官:什么是浏览器的同源策略?解决什么问题?如何避免?​

本文探讨了浏览器的同源策略、gitcherry-pick的用法、iconfont的工作原理,还介绍了JavaScript中数组比较的深浅比较,以及观察者设计模式及其应用场景,最后对比了堆和栈的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

119期

1. 什么是浏览器的同源策略?解决什么问题?如何避免?
2. 什么是git cherry-pick?通常什么场景下使用?
3. iconfont的原理是什么?

上面问题的答案会在第二天的公众号(程序员每日三问)推文中公布

也可以小程序刷题,已收录500+面试题及答案cb347991bdb4d15e16fb4f92145cbff7.jpeg

118期问题及答案

1. js中[]==[]的结果是什么?为什么

在JavaScript中,[] == [] 的结果是 false。它是由JavaScript的比较规则决定的。

JavaScript中的 == 运算符用于比较两个值是否相等。当使用 == 进行比较时,它首先会检查操作数的类型,然后再比较它们的值。对于 [] == [],以下是发生的情况:

  1. 两个空数组被创建。尽管它们的内容是一样的(都是空数组),但它们是两个不同的对象实例。

  2. == 运算符首先比较它们的类型,它们都是对象。

  3. 接下来,它比较它们的引用。由于这两个数组是不同的实例,它们具有不同的引用。

  4. 因此,尽管它们的内容相同,但由于引用不同,[] == [] 的结果是 false

要检查两个数组是否具有相同的内容,你应该使用严格相等运算符 ===,或者使用比较它们的内容,而不是引用的方法。例如,你可以使用 JSON.stringify 将数组转换为字符串,然后进行比较:

JSON.stringify([]) === JSON.stringify([]); // true

这将比较数组的内容而不是它们的引用。

2. 什么是观察者设计模式?通常有哪些应用场景?

观察者设计模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使一个对象(主题或被观察者)的状态发生变化时,所有依赖它的对象(观察者)都会得到通知并自动更新。观察者模式通常包括以下几个角色:

  1. 主题(Subject):也称为被观察者,它维护一组观察者对象,并提供方法来添加、删除和通知观察者。当主题的状态发生变化时,它通知所有注册的观察者。

  2. 观察者(Observer):观察主题的对象,它定义了一个更新接口,用于在主题状态发生变化时接收通知和执行相应操作。

  3. 具体主题(Concrete Subject):主题的具体实现,它维护了一组观察者,状态发生变化时通知观察者。

  4. 具体观察者(Concrete Observer):观察主题的具体实现,实现了观察者接口,并在接收到通知时执行具体的操作。

观察者设计模式的主要目标是实现对象之间的松耦合,使主题和观察者之间的关系动态且可扩展。这种模式在很多应用场景中都非常有用,其中一些典型的应用场景包括:

  1. 事件处理:观察者模式常用于事件处理系统,其中事件源(主题)可以触发事件,而事件处理程序(观察者)订阅并响应事件。

  2. 用户界面:在GUI应用程序中,按钮、文本框等用户界面元素可以作为主题,当它们的状态发生变化时,会通知订阅的UI组件(观察者)更新显示。

  3. 发布-订阅模式:观察者模式是发布-订阅模式的基础,用于构建事件总线或消息队列系统,允许组件订阅和发布消息。

  4. 数据更新:在数据驱动的应用中,当数据模型发生变化时,视图(观察者)需要自动更新以反映最新的数据状态。

  5. 消息通知:在通知系统中,观察者模式可以用来订阅和接收特定类型的消息。

  6. 股票市场:股票市场中的股票价格变化可以作为主题,各种投资者可以作为观察者,订阅股价变化并采取相应的投资行动。

  7. 多语言支持:在多语言应用中,语言选择可以作为主题,UI元素可以作为观察者,以便在语言更改时刷新UI。

观察者设计模式使得系统更具弹性,能够轻松扩展新的观察者,同时保持主题和观察者之间的松耦合。这有助于分离关注点,提高代码的可维护性和可扩展性。 下面我将通过一个示例来说明观察者设计模式的应用场景。假设我们有一个新闻发布系统,新闻编辑器(主题)发布新闻,而订阅者(观察者)是不同的新闻订阅者。当新闻编辑器发布新闻时,所有订阅者都会收到通知并获取最新的新闻。

// 主题(新闻编辑器)
class NewsEditor {
  constructor() {
    this.subscribers = []; // 订阅者列表
  }

  // 添加订阅者
  subscribe(subscriber) {
    this.subscribers.push(subscriber);
  }

  // 移除订阅者
  unsubscribe(subscriber) {
    this.subscribers = this.subscribers.filter(sub => sub !== subscriber);
  }

  // 发布新闻
  publishNews(news) {
    console.log(`发布新闻: ${news}`);
    this.notifySubscribers(news);
  }

  // 通知所有订阅者
  notifySubscribers(news) {
    this.subscribers.forEach(subscriber => {
      subscriber.update(news);
    });
  }
}

// 观察者(新闻订阅者)
class NewsSubscriber {
  constructor(name) {
    this.name = name;
  }

  // 更新方法,用于接收新闻通知
  update(news) {
    console.log(`${this.name} 收到新闻: ${news}`);
  }
}

// 创建新闻编辑器和订阅者
const editor = new NewsEditor();
const subscriber1 = new NewsSubscriber("Subscriber 1");
const subscriber2 = new NewsSubscriber("Subscriber 2");

// 订阅者订阅新闻编辑器
editor.subscribe(subscriber1);
editor.subscribe(subscriber2);

// 发布新闻
editor.publishNews("重要新闻: 今天的头条新闻");

// 输出结果:
// 发布新闻: 重要新闻: 今天的头条新闻
// Subscriber 1 收到新闻: 重要新闻: 今天的头条新闻
// Subscriber 2 收到新闻: 重要新闻: 今天的头条新闻

在上面的示例中,NewsEditor 充当主题,它可以添加订阅者、移除订阅者、发布新闻以及通知订阅者。NewsSubscriber 充当观察者,它通过 update 方法接收新闻通知。当新闻编辑器发布新闻时,所有订阅者都会得到通知并接收最新的新闻。

这个示例演示了观察者设计模式在实际应用中的用途,其中主题和观察者之间的关系是松耦合的,允许轻松地扩展和维护系统。

3. 堆与栈有什么区别?请用代码模拟实现一个?

堆和栈是计算机内存中的两种不同区域,它们有不同的分配方式和使用方式。下面是它们的主要区别:

栈 (Stack):

  1. 分配方式:栈是一种自动分配和释放内存的数据结构,它以一种线性的方式组织数据。

  2. 存储:栈用于存储函数调用的上下文(局部变量、函数参数、返回地址等),以便在函数返回时恢复状态。

  3. 速度:栈操作非常快,因为它是线性的,通常是固定大小。

  4. 生存期:栈上的数据的生存期通常与包含它的函数的生存期相同。

  5. 大小限制:栈的大小通常有限,因此适用于相对小的数据。

堆 (Heap):

  1. 分配方式:堆是一种手动分配和释放内存的数据结构,程序员负责分配和释放内存。

  2. 存储:堆用于存储动态分配的数据,如对象、数组等。

  3. 速度:堆操作相对较慢,因为它的内存分配和释放需要一定的时间。

  4. 生存期:堆上的数据的生存期不与特定函数相关,需要手动释放,否则会造成内存泄漏。

  5. 大小限制:堆的大小通常受系统资源的限制,可以动态分配较大的数据。

下面是一个简单的JavaScript示例,模拟栈和堆的区别:

// 模拟栈
function stackExample() {
  let x = 10;  // 栈上的局部变量
  let y = 20;
  const result = x + y;
  return result;
}

// 模拟堆
function heapExample() {
  const obj = { name: "John", age: 30 }; // 在堆上分配对象
  obj.age = 31; // 修改堆上的对象
  return obj;
}

const stackResult = stackExample();
const heapResult = heapExample();

console.log("栈示例结果:", stackResult);
console.log("堆示例结果:", heapResult);

在上面的示例中,stackExample 函数使用栈存储局部变量 xy,以及计算它们的结果。而 heapExample 函数使用堆分配了一个对象,并在堆上修改了对象的属性。结果,stackResult 存储了一个数字,而 heapResult 存储了一个对象。

需要注意的是,JavaScript中的内存管理通常由JavaScript引擎和垃圾回收器来处理,开发者不需要手动分配和释放内存。上述示例仅用于说明栈和堆的概念。

学习不打烊,充电加油只为遇到更好的自己,每天早上9点纯手工发布面试题,每天坚持花20分钟来学习与思考,在千变万化,类库层出不穷的今天,不要等到找工作时才狂刷题,提倡每日学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值