面试题总结

margin.png

A和B都是距离上边100px;
现在给B设置margin-top:100px;发现两个方块位置没动;
而当给B设置margin-top:150px;小方块B带着大方块A往下移动了50px;

原理:父子嵌套元素在垂直方向的margin,父子元素是结合在一起的,他们两个的margin会取其中最大的值.
正常情况下,父级元素应该相对浏览器进行定位,子级相对父级定位.
但由于margin的塌陷,父级相对浏览器定位.而子级没有相对父级定位,子级相对父级,就像坍塌了一样.

margin塌陷解决方法

1.给父级设置边框或内边距(不建议使用)

.wrapper{
       width:200px;
       height:200px;
       background-color:red;
       margin-top:100px;
       border-top:1px solid black;
}

2.触发bfc(块级格式上下文),改变父级的渲染规则
方法:
改变父级的渲染规则有以下四种方法,给父级盒子添加
(1)position:absolute/fixed
(2)display:inline-block;
(3)float:left/right
(4)overflow:hidden
这四种方法都能触发bfc,但是使用的时候都会带来不同的麻烦,具体使用中还需根据具体情况选择没有影响的来解决margin塌陷

margin合并现象:

原理:两个兄弟结构的元素在垂直方向上的margin是合并的

原理图:

面试题总结

原理图

margin合并题也可以用bfc解决,
1.给box2加上一层父级元素并加上overflow:hidden;

<style>
.wrapper{
            overflow:hidden;
        }
</style>
<div class="box1"></div>
   <div class="wrapper">
        <div class="box2"></div>
  </div>

2.给两个都加一层父级再加bfc

<div class="wrapper">
        <div class="box1"></div>
    </div>
    <div class="wrapper">
        <div class="box2"></div>
    </div>

但是这两种方法都改变了HTML结构,在开发中一般不采用的;
所以在实际应用时,在margin合并这个问题上,我们一般不用bfc,而是通过只设置上面的元素的margin-bottom来解决距离的问题。

10、解释下CSS-BFC

一、何为BFC

BFC(Block Formatting Context)格式化上下文,是Web页面中盒模型布局的CSS渲染模式,指一个独立的渲染区域或者说是一个隔离的独立容器。

二、形成BFC的条件

  1、浮动元素,float 除 none 以外的值; 
  2、定位元素,position(absolute,fixed); 
  3、display 为以下其中之一的值 inline-block,table-cell,table-caption; 
  4、overflow 除了 visible 以外的值(hidden,auto,scroll);

参考:
https://www.cnblogs.com/chen-cong/p/7862832.html
https://www.jianshu.com/p/828023418450

11、看下这行数字的规律,写个方法返回第30位是什么?1,1,2,3,5,8…

function fn(len) {
    if (len < 3) {
        return 1;
    }
    var first = 1, sec = 1, third = 0;
    for (let i = 2; i < len; i++) {
        third = first + sec;
        first = sec; sec = third;
    }
    return third;
}
fn(1); // 1
fn(2); // 1
fn(5); // 5
fn(30); // 832040

这个叫斐波那契数列,另一种实现方式

function fibonacci(n) {
  // 一、递归解法
  return n <= 2 ? 1 : fibonacci(n - 1) + fibonacci(n - 2);
  // 二、循环解法
  // var num1 = 1;
  // var num2 = 1;
  // for (var i = 2; i < n; i++) {
  //   num2 += num1;
  //   num1 = num2 - num1;
  // }
  // return num2;
  // 三、循环解法另一种方式
  // let obj = {
  //   a0: 0,
  //   a1: 1,
  //   a2: 1,
  //   a3: 2,
  // }, i = 0;
  // while (i < n) {
  //   i++;
  //   obj['a' + (i + 2)] = obj['a' + i] + obj['a' + (i + 1)];
  // }
  // return obj['a' + i];
}

12、 javascript的typeof返回哪些数据类型.

答案:string,boolean,number,undefined,function,object

13、例举3种强制类型转换和2种隐式类型转换?

答案:强制(parseInt,parseFloat,number)
隐式(==   ===)

14、split()、join() 的区别

答案:前者是将字符串切割成数组的形式,后者是将数组转换成字符串

15、数组方法pop()、push() 、unshift()、 shift()

答案:push()尾部添加 pop()尾部删除
unshift()头部添加 shift()头部删除

16、IE和标准下有哪些兼容性的写法

答案:

var ev = ev || window.event;
document.documentElement.clientWidth || document.body.clientWidth;
Var target = ev.srcElement || ev.target;

17、innerHTML和outerHTML的区别

答案:
innerHTML(元素内包含的内容)
outerHTML(自己以及元素内的内容)

18、offsetWidth offsetHeight和clientWidth clientHeight的区别

答案:
(1)offsetWidth (content宽度+padding宽度+border宽度)
(2)offsetHeight(content高度+padding高度+border高度)
(3)clientWidth(content宽度+padding宽度)
(4)clientHeight(content高度+padding高度)

19、闭包的好处

答案:
(1)希望一个变量长期驻扎在内存当中(不被垃圾回收机制回收)
(2)避免全局变量的污染
(3)私有成员的存在
(4)安全性提高

20、冒泡排序算法

var array = [5, 4, 3, 2, 1];
var temp = 0;
for (var i = 0; i <array.length; i++){
for (var j = 0; j <array.length - i; j++){
  if (array[j] > array[j + 1]){
    temp = array[j + 1];
    array[j + 1] = array[j];
    array[j] = temp;
  }
}

21、请写出一个打乱JS数组【1,2,3,4,5,6】内元素排列顺序的方法。

function randomsort(a, b) {
    return Math.random() > .5 ? -1 : 1;
}
var arr = [1, 2, 3, 4, 5, 6];
arr.sort(randomsort);

22、不用循环(包括ES5的forEach、map等方法),创建一个长度位100的数组,并且每个元素值等于的下标索引【0,1,2…99】。

// 方法一
Object.keys(Array.from({length:100}));
// 方法二
Object.keys(Array.apply(null,{length:100}));
// 方法三
Object.keys([...Array(100)]);
// 方法四
Object.keys(Array(100).keys());
// 方法五
[...Array(100).keys()];

23、Object.assign用法、特点、模拟实现

答:浅拷贝Object.assign,将所有可枚举属性的值从一个或多个源对象复制到目标对象,同时返回目标对象。

Object.assign(target, …sources)

其中 target 是目标对象,sources 是源对象,可以有多个,返回修改后的目标对象 target。
如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后来的源对象的属性将类似地覆盖早先的属性。
Object.assign 模拟实现
实现一个 Object.assign 大致思路如下:

1、判断原生 Object 是否支持该函数,如果不存在的话创建一个函数 assign,并使用 Object.defineProperty 将该函数绑定到 Object 上。

2、判断参数是否正确(目标对象不能为空,我们可以直接设置{}传递进去,但必须设置值)

3、使用 Object() 转成对象,并保存为 to,最后返回这个对象 to

4、使用 for..in 循环遍历出所有可枚举的自有属性。并复制给新的目标对象(hasOwnProperty返回非原型链上的属性)

实现代码如下,这里为了验证方便,使用 assign2 代替 assign。注意此模拟实现不支持 symbol 属性,因为ES5 中根本没有 symbol 。

if (typeof Object.assign2 != 'function') {
  Object.defineProperty(Object, "assign2", {
    value: function (target) {
      'use strict';
      if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object');
      }
      var to = Object(target);
      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index];
        if (nextSource != null) {
          for (var nextKey in nextSource) {
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey];
            }
          }
        }
      }
      return to;
    },
    writable: true,
    configurable: true
  });
}

24、封装函数 f,使 f 的 this 指向指定的对象

答:

function bindThis(f, oTarget) {
    return f.bind(oTarget);
}

25、获取 url 中的参数

  1. 指定参数名称,返回该参数的值 或者 空字符串
  2. 不指定参数名称,返回全部的参数对象 或者 {}
  3. 如果存在多个同名参数,则返回数组
    答:
function getUrlParam(sUrl, sKey) {
  let obj = {}, sArr = sUrl.split("?")[1].split("#")[0].split("&");
  sArr.forEach(item => {
    let [key, value] = item.split("=");
    obj[key] = obj.hasOwnProperty(key) ? [].concat(obj[key], value) : value;
  });
  return sKey === undefined ? obj : obj[sKey] || "";
}

26、查找两个节点的最近的一个共同父节点,可以包括节点自身(oNode1 和 oNode2 在同一文档中,且不会为相同的节点)

答:

function commonParentNode(oNode1, oNode2) {
  while (!oNode1.contains(oNode2)) {
    oNode1 = oNode1.parentNode;
  }
  return oNode1;
}

27、为 Array 对象添加一个去除重复项的方法

示例1:
输入描述:

[false, true, undefined, null, NaN, 0, 1, {}, {}, ‘a’, ‘a’, NaN]

输出描述:

[false, true, undefined, null, NaN, 0, 1, {}, {}, ‘a’]

答:

Array.prototype.uniq = function () {
    return [...new Set(this)];
}

28、根据包名,在指定空间中创建对象

示例1:
输入描述:

namespace({a: {test: 1, b: 2}}, ‘a.b.c.d’)

输出描述:

{a: {test: 1, b: {c: {d: {}}}}}

答:

function namespace(oNamespace, sPackage) {
  if (!sPackage || Object.prototype.toString.call(oNamespace) !== "[object Object]") {
    return oNamespace || {};
  }
  let arr = sPackage.split('.');
  const key = arr.shift();
  if (arr.join(".") && Object.prototype.toString.call(oNamespace[key]) !== "[object Object]") {
    oNamespace[key] = {};
  }
  oNamespace[key] = namespace(oNamespace[key], arr.join("."));
  return oNamespace || {};
}

29、时间格式化输出,按所给的时间格式输出指定的时间

格式说明
对于 2014.09.05 13:14:20
yyyy: 年份,2014
yy: 年份,14
MM: 月份,补满两位,09
M: 月份, 9
dd: 日期,补满两位,05
d: 日期, 5
HH: 24制小时,补满两位,13
H: 24制小时,13
hh: 12制小时,补满两位,01
h: 12制小时,1
mm: 分钟,补满两位,14
m: 分钟,14
ss: 秒,补满两位,20
s: 秒,20
w: 星期,为 [‘日’, ‘一’, ‘二’, ‘三’, ‘四’, ‘五’, ‘六’] 中的某一个,本 demo 结果为 五

示例1:
输入描述:

formatDate(new Date(1409894060000), ‘yyyy-MM-dd HH:mm:ss 星期w’)

输出描述:

2014-09-05 13:14:20 星期五

答:正则的就不写了,网上一堆,写个不用正则的,

function formatDate(date, format) {
  // 写个不用正则的方法
  // obj的 key 顺序必须是 yyyy 在 yy 前面,MM 在 M 前......,为下面replace准备
  let obj = {
    yyyy: date.getFullYear(), // 2021
    yy: (date.getFullYear()).toString().substr(2, 4), // 21
    MM: ("0" + (date.getMonth() + 1)).slice(-2), // 01
    M: date.getMonth() + 1, // 1
    dd: ("0" + date.getDate()).slice(-2),
    d: date.getDate(),
    HH: ("0" + date.getHours()).slice(-2), // 24制小时
    H: date.getHours(),
    hh: ("0" + date.getHours() % 12).slice(-2), // 12制小时
    h: date.getHours() % 12,
    mm: ("0" + date.getMinutes()).slice(-2),
    m: date.getMinutes(),
    ss: ("0" + date.getSeconds()).slice(-2),
    s: date.getSeconds(),
    w: "日一二三四五六".charAt(date.getDay()),
  };
  for (let key in obj) {
    format = format.replace(key, obj[key]);
  }
  return format;
}

30、获取字符串的长度

如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1
否则如果字符 Unicode 编码 > 255 则长度为 2
示例1:
输入描述:

‘hello world, 哈哈’, false

输出描述:

17

答:

function strLength(s, bUnicode255For1) {
  if (!bUnicode255For1) {
    let len = s.length;
    for (let i = 0; i < len; i++) {
      if (s.charCodeAt(i) > 255) {
        len++;
      }
    }
    return len;
  }
  return s.length;
}

31、邮箱字符串判断

判断输入是否是正确的邮箱格式
示例1:
输入描述:

邮箱字符串

输出描述:

true表示格式正确

答:

function isAvailableEmail(sEmail) {
  return /^([\w+\.])+@(\w+)([.]\w+)+$/.test(sEmail);
}

32、颜色字符串转换

将 rgb 颜色字符串转换为十六进制的形式,如 rgb(255, 255, 255) 转为 #ffffff

  1. rgb 中每个 , 后面的空格数量不固定
  2. 十六进制表达式使用六位小写字母
  3. 如果输入不符合 rgb 格式,返回原始输入
    示例1:
    输入描述:

‘rgb(255, 255, 255)’

输出描述:

#ffffff

答:可以用正则来实现更简单点,可是我不太熟悉正则,不过JS也可以实现

function rgb2hex(sRGB) {
  const sRGBSave = sRGB;
  if (sRGBSave.substr(0, 4) !== "rgb(") {
    return sRGBSave;
  }
  sRGB = sRGB.split("(")[1].split(",");
  if (sRGB.length !== 3) {
    return sRGBSave;
  }
  let res = "#";
  for (let i = 0; i < 3; i++) {
    const item = parseFloat(sRGB[i]);
    if (isNaN(item) || item < 0 || item > 255) {
      return sRGBSave;
    }
    res += ("0" + (item).toString(16)).slice(-2);
  }
  return res;
}

33、将字符串转换为驼峰格式

css 中经常有类似 background-image 这种通过 – 连接的字符,通过 javascript 设置样式的时候需要将这种样式转换成 backgroundImage 驼峰格式,请完成此转换功能

  1. 以 – 为分隔符,将第二个起的非空单词首字母转为大写
  2. -webkit-border-image 转换后的结果为 webkitBorderImage
    示例1:
    输入描述:

‘font-size’

输出描述:

fontSize

答:

function cssStyle2DomStyle(sName) {
  sName = sName.split("-");
  let str = "";
  for (let key in sName) {
    if (sName[key]) {
      let first = sName[key].slice(0, 1);
      if (str) {
        first = first.toUpperCase();
      }
      let tail = sName[key].slice(1 - sName[key].length);
      str += first + tail;
    }
  }
  return str;
}

34、字符串字符统计

统计字符串中每个字符的出现频率,返回一个 Object,key 为统计字符,value 为出现频率

  1. 不限制 key 的顺序
  2. 输入的字符串参数不会为空
  3. 忽略空白字符
    示例1:
    输入描述:

‘hello world’

输出描述:

{h: 1, e: 1, l: 3, o: 2, w: 1, r: 1, d: 1}

答:
第一种

function count(str) {
    var obj = {};
    // \S,匹配非空字符串,function(s)里的s代表匹配到的每一项
    str.replace(/\S/g,function(s){
        !obj[s] ? obj[s]=1 : obj[s]++;
    })
    return obj;
}

第二种

function count(str) {
  let obj = {};
  for (let i = 0; i < str.length; i++) {
    if (str.charAt(i) !== " ") {
      obj[str.charAt(i)] = obj.hasOwnProperty(str.charAt(i)) ? ++obj[str.charAt(i)] : 1;
    }
  }
  return obj;
}

35、算法题:跳台阶

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
示例1:
输入描述1:

1

输出描述1:

1

输入描述2:

4

输出描述2:

5

答:

function jumpFloor(number) {
  let obj = { 1: 1, 2: 2 };
  for (let i = 3; i <= number; i++) {
    obj[i] = obj[i - 1] + obj[i - 2];
  }
  return obj[number];
}

36、JavaScript数组扁平化

答:reduce遍历数组每一项,若值为数组就递归遍历,否则cancat。(也可以用map遍历方法或者,toString&split (join&split)调用数组的toString方法,将数组变为字符串后用split分割为数组。)

function flatten(arr) {  
    return arr.reduce((result, item)=> {
        return result.concat(Array.isArray(item) ? flatten(item) : item);
    }, []);
}

文章均来自互联网如有不妥请联系作者删除QQ:314111741 地址:http://www.mqs.net/post/14916.html

相关阅读

  • 淘宝怎么运营推广(中小卖家必学的操作思路)

    淘宝怎么运营推广(中小卖家必学的操作思路)

    淘宝在很长一段时间内,一直被认为是中国最大的电子商务平台。人们在这里购物,与在别处购物一样,会感觉到很便捷、很实惠。因此,随着电商行业的发展。如今,淘宝网站的活跃用户数已经超过了1亿人(目前该数据仅统计了部分用户)。而作为一个淘宝...

    2025.12.09 14:15:37作者:iseeyuTags:运营
  • 如何保证缓存和数据的双写一致性

    如何保证缓存和数据的双写一致性

    image 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存。又或者是先删除缓存,再更新数据库,其实大家存在很大的争议。目前没有一篇全面的博客,对这几种方案进行解析。于是博主战战兢兢,顶着被大家喷的风险,写了这篇...

    2025.12.09 09:28:14作者:iseeyu
  • 【百度搜索引擎优化】如何快速了解百度搜索引擎优化的知识?(搜索引擎优化基本)

    【百度搜索引擎优化】如何快速了解百度搜索引擎优化的知识?(搜索引擎优化基本)

    在百度输入SEO优化,下拉框就有很多关键词,SEO优化工具,SEO查询,SEO技巧,SEO优化方案,SEO报价,SEO优化教程,SEO优化软件,SEO优化怎么做,等等,相关搜索也有很多长尾关键词。还可以加入一些群,找些大牛问下,向这些大牛学...

    2025.12.09 07:37:38作者:iseeyu

添加新评论