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 中的参数
- 指定参数名称,返回该参数的值 或者 空字符串
- 不指定参数名称,返回全部的参数对象 或者 {}
- 如果存在多个同名参数,则返回数组
答:
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
- rgb 中每个 , 后面的空格数量不固定
- 十六进制表达式使用六位小写字母
- 如果输入不符合 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 驼峰格式,请完成此转换功能
- 以 – 为分隔符,将第二个起的非空单词首字母转为大写
- -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 为出现频率
- 不限制 key 的顺序
- 输入的字符串参数不会为空
- 忽略空白字符
示例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
添加新评论