前端面试题(一)

本文最后更新于:2025年1月29日 凌晨

H5新特性

  • 拖拽释放(Drap and drop) API ondrop
  • 自定义属性 data-id
  • 语义化标签,header、nav、footer、aside、article、section
  • 音频自动播放属性 autoplay
  • 画布 Canvas
  • 离线存储 localStorage、会话存储 sessionStorage
  • 表单控件,calendar、date、time、email、url、search
  • 新技术,web worker、web socket、geolocation

C3新特性

  • 颜色新增,RGBA、HSLA模式
  • 文字阴影,text-shadow
  • 盒模型,box-sizing
  • 渐变,linear-gradient、radial-gradient
  • 过度,transition <animation-name>
  • 自定义动画 animate @keyframe
  • 媒体查询,@media screen and (max-width: 800px) { … }
  • 弹性布局,flex

H5浏览器存储有哪些

  • cookie,在控制台输入document.cookie 可以看到当前页面的cookie值,是一个字符串,以分号分隔'_octo=GH1.1.647075200.1634350299; tz=Etc%2FGMT-8'。cookie 始终在同源的 http 请求中携带。
  • localStorage,本地化持久存储,只要用户不删除,就一直存在。在控制台输入sessionStorage 得到 Storage {length: 0}
  • sessionStorage,面向session 的浏览器存储,因此只存在于一个页面的生命周期内。在控制台输入localStorage得到 Storage {ref-selector:helloqingfeng/Awsome-Front-End-learning-resource:branch: '{"refs":["master","gh-pages"],"cacheKey":"v0:1472661172.0"}', ref-selector:baozouai/shop-admin:branch: '{...}'
  • indexedDB,IDBFactory {}
  • window对象上的全局变量

盒子水平垂直居中

  • margin: 0 auto;
  • display: table-cell;
  • display: flex; jusitify-content: center; align-items: center;
  • .parent { position: relative } .child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)}

CSS盒模型

  • box model 指的是css 中所有元素都可以看作是一个个的盒子,包括内容、内边距、边框、外边距。
  • 盒模型分两种
    • w3c 标准盒模型,称为标准盒模型。height 属性指的是 content 内容区域的大小
    • ie 标准盒模型,怪异盒模型。height 属性指的是 content+border+padding 的大小

块级元素和行内元素的区别

  • 块级元素占一行,填满父元素。可以设置 width、height、margin、padding 属性
  • 行内元素随着内容宽度变化而变化。自动换行。宽高无效,水平方向的margin、padding有效

选择器权重

  • !important > 行内样式 > ID 选择器 > 类选择器、伪类、属性 > 标签、伪元素 > 通配符 > 继承 > 浏览器默认属性
  • 权重计算方式为选择符中ID 选择器的数量 x 100 + 类、伪类、伪元素的数量 x 10 + 标签、伪元素的数量div#app.child[name=”appName”] 的权重值为 a=1,b=2,c=1 ➡ 1+100+10x2 = 121

语义化标签

  • 利用html 的原生样式减少css 样式的书写。
  • 有利于SEO ,便于浏览器理解页面结构
  • 样式丢失的时候也能呈现较为清晰的页面结构
  • 常见的语义化标签
    • <header><section><article><aside><footer>

H5 事件举例

  • 通过 on+<事件名字> 的形式,作为元素的属性进行指定
  • onblur 失去焦点、onchange 元素改变、onclick 单击鼠标、onkeydown 按下按键时候触发、onkeypress 按下并松开时触发、onkeyup 松开按键时触发。

H5 input 元素 type 值举例

  • button、checkbox、color 拾色器、date 日期字段、month 定义月、time 定义时间、email、file、hidden 隐藏输入字段、image 输入图像、number 带有微调spinner 控件的字段、password、radio、search、submit、text、url

css 三角形制作

  • 画三角形的实质是设置内容宽高为0,显示其中一条边界线
  • .triangle { width: 0; height: 0; border 50px solid transparent; border-bottom: 100px solid green;}

css 中的单位,px、em、rem

  • px 像素,绝对单位,相对于显示器屏幕分辨率而言。是计算机系统的数字化图像长度单位
  • em 相对于当前元素内文本的字体尺寸
  • rem 相对于根元素的字体尺寸, html 根元素默认 16px。

display: none 和 visibility: hidden 区别

  • display: none 元素隐藏,占据的空间消失
  • visibility: hidden 元素不可见,仍然占据页面空间

position 属性的值有哪些

  • static:元素默认值
  • relative:相对于元素原来在文档流中的定位
  • absolute:相对于最近的非 static 定位祖先元素进行定位
  • fixed:相对于相对于屏幕视口(viewport)的位置进行定位
  • sticky:相对它的最近滚动祖先和最近块级祖先进行定位

雪碧图

  • 将网站上用到的一些图片合并到一张图片上,通过减少网络请求来提高性能
  • 缺点,图片位置需要精确的指定,利用background、background-position 属性,增加了css 样式的编写难度。

css3 新增伪类,伪元素

  • :first-of-type 父元素的首个p元素、:last-of-type 最后的p元素
  • :nth-child(n) 括号中表达式(an+b)匹配到的元素集合(n=0,1,2,3…),还有odd、even 可用
  • :not(p) 非p元素、:enabled 表单控件的可用状态、:disabled 禁用表单控件、:checked 单选框或者复选框被选中。
  • ::first-line 样式添加到文本的首字母,::first-line 样式添加到文本的首行。
  • 低版本的IE中,不兼容双冒号,继续使用单冒号的伪元素。
  • 伪元素一般指的是特殊位置,而伪类,是特殊状态

图片懒加载原理

  • 核心是,监控图片位置,在合适的位置将其加载出来。
  • 设置图片的data-set 属性,为图片的url。当图片的顶点坐标Y小于页面和浏览器高度时,将data-set 内url 属性赋值给src。涉及到的API包括obj.getBoundingClientRect().top;document.documentElement.clientHeight;

JS 基本类型,引用类型

  • 基本数据类型:number, string, boolean, null, undefined
  • 引用数据类型:function, object, Array
  • undefined 表示变量声明但是未初始化的值
  • null 表示准备用来保存对象,但还没有真正保存对象的值
  • undefined 派生至 null

创建对象的几种方式

  • 字面量对象, let o1 = { name: '01'}
  • new 一个对象,let o2 = new Object({ name: '02'})
  • 显式的构造函数,let o3 = function() { this.name = '03'};
  • Object.create(),let o = { name: '04'}; let o3 = Object.create(o)

区分数组和对象

  • Array.isArray(),
    • Aarray.isArray([]) // true
    • Array.isArray({}) // false
  • instanceof,
    • [] instanceof Array // true
    • {} instanceof Array // false
  • constructor,
    • {}.constructor // 返回object
    • [].constructor // 返回Array
  • Object.prototype.toString.call(),
    • Object.prototype.toString.call([]) //[“object Array”]
    • Object.prototype.toString.call({}) // [“object Object”]

伪数组(类数组)转化

  • 伪数组具有length 属性,以及按照数组索引的方式存储数据。
  • 转化方式
    • Array.from()
    • [].slice.call(eleArr) 或者 Array.prototype.slice.call(eleArr)

遍历对象属性

  • Object.keys() 可枚举,非继承属性。for…in 还包括继承的可枚举属性
  • Object.getOwnPropertyNames() 可枚举,不可枚举,非继承属性
  • hasOwnProperty() 判断对象是否有某个属性

src 和 href 区别

  • src (source) 资源,指向的内容会嵌入到标签所在位置,比如脚本,图片,iframe。解析到此类元素时。浏览器会暂停其他元素的下载和处理。知道将该元素加载、编译、执行完毕。
  • href (hypertext reference) 建立和当前元素的链接。会并行下载i资源,不会停止对当前文档的处理。

dom 事件模型

  • 元素发生一个事件,父元素也感受到了。那么就有了一个先后执行的问题。
  • 事件由根元素开始触发,向内传播 —— 事件捕获
  • 事件由目标元素,一直传播到根元素 —— 事件冒泡
  • addEventListener 默认为事件冒泡机制
  • 可以用 e.stopPropagation(); 或者 return false; 或者 e.preventDefault(); 停止事件在冒泡链上进一步扩大

js 定时器

  • setTimeout() —— 在指定毫秒数后运行函数,一般用来模拟异步操作。
  • setInterval() —— 按照设置的时间间隔运行函数,直到 clearInterval() 或者窗口被关闭

回调函数

  • 软件模块之间的接口,从调用方式上可以分为 3 类,同步调用、异步调用、回调
  • 同步调用就是通常所说的调用函数,一步一步执行,这是一种阻塞式调用,函数执行完毕才会返回。
  • 异步调用,是一种类似于消息或者事件的机制。接口的服务在收到某种讯息或发生某种事件的时候,主动通知调用方。
  • 回调函数就是一个通过函数指针调用的函数。把函数指针(地址)作为函数参数传递给另一个函数。

什么是闭包

  • 闭包,closure,可以理解为一个封闭空间,一个定义在函数内部的函数。它可以通过作用域链访问外部函数的变量空间
  • 可以利用闭包的这个性质,保存外部变量,当然也会造成一些性能损失。

原型的理解

  • 原型的作用是为了实现继承,和扩展对象的一种代码重用机制
  • js 中的所有元素,都可以看作是对象,他们都有一个 prototype 属性,它的值是一个对象,叫做原型,这个prototype 属性又有自己的 prototype 属性。最终链接到 Object 对象。
  • prototype 属性,有一个 constructor 属性。可以用来构造对象的实例。

说下 this

  • this 是一个标识符,用来指代函数执行的上下文执行环境
  • 讲 this,就一定要说一下对象的构造机制。在构造对象的时候,this 赋值为一个Object 实例,然后向其中添加属性方法。那么,对这个对象内部的函数,this 可以在它的变量表中,找到 this 所指代的对象。
  • 那么一般地调用对象内部的方法,this 就是 函数前面的对象。从对象可以找到函数,那么函数内部的this, 指的就是这个对象。
  • 另一个函数回调,要通过apply、call 手动声明函数的执行上下文,this 指代的是什么。
  • 箭头函数,没有自己的this, 它使用的是自己定义环境中的this 指代的对象。通过作用域链是使用this。

统计出现最多的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var obj = {}; // 先定义一个空对象,稍后使用.
var maxChar=''; // 要输出的字符
var maxN=0;// 字符数量

for (var i = 0; i < str.length; i++) { // 循环字符串中每一项
var k = str[i]; // 把每一项保存给变量 k (对这一步不理解可先熟悉 for循环机制);

if (obj[k]) {

obj[k]++;
} else {
obj[k] = 1;
}
if(obj[k]>maxN){
maxChar=k;
maxN=obj[maxChar];
}
}
console.log(maxChar, maxN);

内存泄漏

  • 一些不再使用的变量,依然占据着内存空间,称为内存泄漏,(浪费掉了)

事件循环

  • js 是一个单线程的语言。这意味着同一时间只能做一件事。
  • 单线程不意味着阻塞,实现单线程非阻塞的方法是事件循环
  • js 中的任务可以分为同步任务和异步任务
    • 同步任务就是立即执行的任务,会直接进入到主线程中执行
    • 异步任务,异步执行的任务,比如ajax网络请求,setTimeout 定时函数
    • 同步任务执行完毕,就会去任务队列中的任务,推入主线程执行。
  • 异步任务又分为宏任务和微任务
    • 执行机制为执行完宏任务后,执行所有微任务。再进行查看是有宏任务
    • 常见的微任务有,Promise.then,MutationObserver,process.nextTick

Promise

  • promise 是一个有状态的对象
  • 将异步操作的结果和对应的处理函数结合起来
  • 将异步操作以同步操作的流程表达出来,避免回调地狱
  • Promise 的构造函数接收一个回调,回调有两个参数 resolve reject,成功就调用resolve,表示promise 状态fulled,结果为resolve 返回的结果。实例化的Promise,返回的对象可以调用 then() 方法,then() 方法接收两个参数,onResolve 和 onReject 对应promise 成功或者失败的状态

手写 Promise

  • ```js
    class Promise {

    constructor(handler) {
        // define initial state
        this.status = "pending";
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
        
        // define basic transition function
        const resolve = value => {
            if (this.status === "pending") {
                this.status = "fulfilled";
                this.value = value;
                this.onFulfilledCallbacks.forEach(fn => fn(value));
            }
        };
    
        const reject = value => {
            if (this.status === "pending") {
                this.status = "rejected";
                this.value = value;
                this.onRejectedCallbacks.forEach(fn => fn(value));
            }
        };
    
        try {
            // call outer function passed in
            handler(resolve, reject);
        } catch (err) {
            reject(err);
        }
    }
    
    then(onFulfilled, onRejected) {
        // support chain call
        return new Promise((resolve, reject) => {
            // define handler
            if (this.status === "pending") {
                this.onFulfilledCallbacks.push(() => {
                    try {
                        // if return value is promise, resolve it.
                        const fulfilledFromLastPromise = onFulfilled(this.value);
                        if (fulfilledFromLastPromise instanceof Promise) {
                            fulfilledFromLastPromise.then(resolve, reject);
                        } else {
                            resolve(fulfilledFromLastPromise);
                        }
                    } catch (err) {
                        reject(err);
                    }
                });
                this.onRejectedCallbacks.push(() => {
                    try {
                        const rejectedFromLastPromise = onRejected(this.value);
                        if (rejectedFromLastPromise instanceof Promise) {
                            rejectedFromLastPromise.then(resolve, reject);
                        } else {
                            reject(rejectedFromLastPromise);
                        }
                    } catch (err) {
                        reject(err);
                    }
                });
            }
    
            if (this.status === "fulfilled") {
                try {
                    const fulfilledFromLastPromise = onFulfilled(this.value);
                    if (fulfilledFromLastPromise instanceof Promise) {
                        fulfilledFromLastPromise.then(resolve, reject);
                    } else {
                        resolve(fulfilledFromLastPromise);
                    }
                } catch (err) {
                    reject(err);
                }
    
            }
    
            if (this.status === "rejected") {
                try {
                    const rejectedFromLastPromise = onRejected(this.value);
                    if (rejectedFromLastPromise instanceof Promise) {
                        rejectedFromLastPromise.then(resolve, reject);
                    } else {
                        reject(rejectedFromLastPromise);
                    }
                } catch (err) {
                    reject(err);
                }
            }
        });
    
    }
    

    }

    // testing code
    let p1 = new Promise((resolve, reject) => {

    setTimeout(() => resolve('resolved first one'), 1000);
    

    });
    p1.then((res) => {

    console.log(res);
    return new Promise(resolve => {
        setTimeout(() => resolve('resolved second one'), 1000);
    });
    

    }).then(res => {

    console.log(res);
    

    });

    // 1 sec later, ‘resolved first one’
    // 1 sec later, ‘resolved second one’

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

    实现 Promise.all, Promise.race, Promise.resolve and Promise.reject

    - ```js
    Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
    let counter = 0;
    const result = [];
    for (let i = 0; i < promises.length; i++) {
    // resolve revery promise, return result when every resolved
    // when reject, return reject(err)
    Promise.resolve(promises[i]).then(res => {
    result[i] = res;
    counter += 1;
    // this check need to be here, otherwise counter would remain 0 till forloop is done
    if (counter === promises.length) {
    resolve(result);
    }
    }, err => {
    reject(err);
    });
    }
    });
    };

    const promise1 = Promise.resolve(3);
    const promise2 = 42;
    const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'foo');
    });

    const newPromise = Promise.all([promise1, promise2, promise3]).then((values) => {
    console.log(values);
    });

    // after 100ms, output: Array [3, 42, "foo"]
  • ```js
    Promise.race = function (promises) {

    return new Promise((resolve, reject) => {
        for (let p of promises) {
            // iterate every promise, return the first one
            Promise.resolve(p).then(res => resolve(res), err => reject(err));
        }
    });
    

    }

    // testing
    const promise1 = new Promise((resolve, reject) => {

    setTimeout(resolve, 500, 'one');
    

    });
    const promise2 = new Promise((resolve, reject) => {

    setTimeout(resolve, 100, 'two');
    

    });
    Promise.race([promise1, promise2]).then((value) => {

    console.log(value);
    // Both resolve, but promise2 is faster
    

    }, err => console.log(err));
    // expected output: “two”

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    - ```js
    Promise.resolve = function (value) {
    if (value instanceof Promise) {
    return value;
    } else {
    return new Promise((resolve, reject) => {
    resolve(value);
    });
    }
    };

    Promise.reject = function (reason) {
    return new Promise((resolve, reject) => reject(reason));
    }

    const p1 = Promise.resolve1("Success");
    p1.then(res => console.log(res)); // "Success"
    const p2 = Promise.reject1("No");
    p2.then(_ => { }, err => console.log(err)); // "No"

前端面试题(一)
https://hercules11.github.io/blog/2022/01/14/前端面试题(一)/
作者
wxc
发布于
2022年1月14日
许可协议