No78.精选前端面试题,享受每天的挑战和学习

简介: No78.精选前端面试题,享受每天的挑战和学习

1px边框问题怎么解决的

在实际开发中,1px边框问题指的是在高分辨率屏幕上显示为模糊或厚度不一致的边框。这是由于高分辨率屏幕的设备像素比(device pixel ratio)较大,导致以传统1个物理像素宽度定义的边框在显示中被缩放并且不再保持细腻的外观。

有几种常见的解决方案可以解决1px边框问题:

  1. 使用CSS的 border-widthborder-image 属性:可以使用 border-width: 1px; 并结合 border-image 属性来创建细腻且一致的边框效果。
.element {
  border-width: 1px;
  border-style: solid;
  border-image: linear-gradient(to right, transparent, rgba(0, 0, 0, 0.5), transparent);
}
  1. 使用像素单位加倍:可以将边框宽度设置为2px,并结合 transform: scale(0.5); 缩小元素的一半大小来模拟1px边框效果。
.element {
  border-width: 2px;
  transform: scale(0.5);
  transform-origin: top left;
}
  1. 使用伪元素并进行缩放:可以使用伪元素来创建额外的边框,并将其缩小一半大小来模拟1px边框。
.element {
  position: relative;
}
.element::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  border: 1px solid;
  transform: scale(0.5);
  transform-origin: top left;
}

这些解决方案都可以在高分辨率屏幕上创建更细腻和一致的1px边框效果。具体选用哪种方法取决于具体需求和实现环境。

手写一个new

当你使用 new 关键字创建一个对象时,实际上发生了以下几个步骤:

  1. 创建一个空对象。
  2. 将新创建的对象的原型链指向构造函数的原型对象。
  3. 将构造函数的执行上下文指向新创建的对象。
  4. 使用新创建的对象作为构造函数的执行上下文来执行构造函数,并获取返回值。
  5. 如果构造函数的返回值是一个对象,则返回该对象;否则,返回新创建的对象。

下面是一个简单的手写实现 new 的示例:

function myNew(constructor, ...args) {
  // 创建一个空对象,指定原型链为构造函数的原型对象
  const obj = Object.create(constructor.prototype);
  // 使用新对象作为构造函数的执行上下文来执行构造函数
  const result = constructor.apply(obj, args);
  // 如果构造函数返回的是一个对象,则返回该对象
  if (typeof result === 'object' && result !== null) {
    return result;
  }
  // 否则返回新对象
  return obj;
}

使用示例:

function Person(name) {
  this.name = name;
}
Person.prototype.sayHello = function() {
  console.log('Hello, ' + this.name);
};
const john = myNew(Person, 'John');
john.sayHello(); // 输出: Hello, John

在上述示例中,我们定义了一个 Person 构造函数,然后使用 myNew 实现了一个简单的 new 方法。通过调用 myNew(Person, 'John'),我们创建了一个 Person 的实例对象 john,并成功调用了 sayHello 方法。

组合寄生解决了组合继承的什么问题

组合寄生式继承是一种继承模式,它可以解决组合继承中的一个问题,即避免了在调用父类构造函数时多次执行父类的构造逻辑。

组合继承是指将原型链继承和借用构造函数继承结合起来的一种继承方式。

它通过使用 Object.create 方法继承父类的原型,并在子类构造函数内部通过调用父类构造函数来继承父类的实例属性。

这样做的结果是,每当创建子类的实例时,都会调用两次构造函数:

  • 一次是在继承父类原型时调用
  • 一次是在子类构造函数内部调用。

而组合寄生式继承则通过创建一个中间对象来解决这个问题。

它使用 Object.create 方法继承父类的原型,并将该中间对象作为子类原型的原型。

然后,通过调用父类构造函数来继承父类的实例属性。

这样一来,在创建子类的实例时,只需要调用一次构造函数,即在子类构造函数内部调用父类构造函数。

这样就避免了多次执行父类的构造逻辑,提高了性能效率。

下面是一个利用组合寄生式继承的示例:

function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log('Hello, ' + this.name);
};
function Child(name, age) {
  Parent.call(this, name); // 继承父类的实例属性
  this.age = age;
}
// 继承父类的原型
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 指定子类的构造函数
Child.prototype.sayAge = function() {
  console.log('I am ' + this.age + ' years old');
};
const child = new Child('John', 21);
child.sayHello(); // 输出: Hello, John
child.sayAge(); // 输出: I am 21 years old

在上述示例中,Child 构造函数使用 Parent.call(this, name) 继承了父类 Parent 的实例属性,而 Child.prototype 使用 Object.create(Parent.prototype) 继承了父类的原型。通过这样的继承方式,子类的实例既拥有了父类的实例属性,也能够使用父类的原型方法,同时避免了调用父类构造函数的重复执行。

原型链讲一下,__proto__是标准吗

原型链是 JavaScript 中实现对象继承的一种机制。每个对象都有一个内部属性 [[Prototype]](也称为 __proto__)。通过原型链,对象可以从其原型对象(也可以是其他对象的原型对象)继承属性和方法。

当访问对象的属性或方法时,如果对象本身没有该属性或方法,JavaScript 引擎会沿着对象的原型链依次查找,直到找到该属性或方法或者到达原型链的末端(即 null)为止。这个查找过程可以形成一个链状结构,即原型链。

可以使用 Object.setPrototypeOf(obj, prototype) 方法来动态修改一个对象的原型,或者使用字面量方式创建对象时使用 Object.create(proto) 来指定对象的原型。此外,ES6 引入了 classextends 关键字,也提供了更简便的方式来实现对象之间的继承。

关于 __proto__,在 ES6 标准中,它被标识为非标准的原型访问方式。尽管大多数现代浏览器对于 __proto__ 提供了支持,但它并不被推荐使用,因为它不是标准规范的一部分。为了更加规范和可靠地访问对象的原型,可以使用 Object.getPrototypeOf(obj) 方法来获取对象的原型,使用 Object.setPrototypeOf(obj, prototype) 方法来设置对象的原型。

以下是一个使用原型链的简单示例:

// 创建一个原型对象
const animal = {
  type: 'unknown',
  sound: function() {
    console.log('The ' + this.type + ' makes a sound.');
  }
};
// 创建一个继承自原型对象的子对象
const dog = Object.create(animal);
dog.type = 'dog';
dog.bark = function() {
  console.log('The dog barks.');
};
// 调用继承自原型的方法
dog.sound(); // 输出: The dog makes a sound.
dog.bark(); // 输出: The dog barks.

在上述示例中,dog 对象继承自 animal 对象,并且它们之间形成了原型链关系。dog 对象可以访问原型对象 animal 的属性和方法,比如调用了 sound 方法。

相关文章
|
1月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
43 0
|
17天前
|
前端开发 开发者 C++
独家揭秘:前端大牛们如何高效学习新技术,保持竞争力!
【10月更文挑战第31天】前端技术飞速发展,如何高效学习新技术成为关键。本文通过对比普通开发者与大牛们的策略,揭示了高效学习的秘诀:明确目标、主动探索、系统资源、实践应用和持续学习。通过这些方法,大牛们能更好地掌握新技术,保持竞争力。示例代码展示了如何通过实践加深理解。
36 4
|
1月前
|
算法 前端开发 Java
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
这篇文章总结了单链表的常见面试题,并提供了详细的问题分析、思路分析以及Java代码实现,包括求单链表中有效节点的个数、查找单链表中的倒数第k个节点、单链表的反转以及从尾到头打印单链表等题目。
33 1
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
|
26天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
61 1
|
1月前
|
Java 应用服务中间件 程序员
JVM知识体系学习八:OOM的案例(承接上篇博文,可以作为面试中的案例)
这篇文章通过多个案例深入探讨了Java虚拟机(JVM)中的内存溢出问题,涵盖了堆内存、方法区、直接内存和栈内存溢出的原因、诊断方法和解决方案,并讨论了不同JDK版本垃圾回收器的变化。
30 4
|
2月前
|
Web App开发 前端开发 Linux
「offer来了」浅谈前端面试中开发环境常考知识点
该文章归纳了前端开发环境中常见的面试知识点,特别是围绕Git的使用进行了详细介绍,包括Git的基本概念、常用命令以及在团队协作中的最佳实践,同时还涉及了Chrome调试工具和Linux命令行的基础操作。
「offer来了」浅谈前端面试中开发环境常考知识点
|
1月前
|
JavaScript 前端开发 Java
VUE学习四:前端模块化,ES6和ES5如何实现模块化
这篇文章介绍了前端模块化的概念,以及如何在ES6和ES5中实现模块化,包括ES6模块化的基本用法、默认导出与混合导出、重命名export和import,以及ES6之前如何通过函数闭包和CommonJS规范实现模块化。
85 0
VUE学习四:前端模块化,ES6和ES5如何实现模块化
|
1月前
|
前端开发 JavaScript 小程序
前端新机遇!为什么我建议学习鸿蒙?
【10月更文挑战第4天】前端新机遇!为什么我建议学习鸿蒙?
113 0
前端新机遇!为什么我建议学习鸿蒙?
|
1月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
126 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
1月前
|
Web App开发 JavaScript 前端开发
前端Node.js面试题
前端Node.js面试题
下一篇
无影云桌面