自用面试题

176 阅读6分钟

css兼容性有哪几种处理方案

主要从4个方面讨论一下大的解决思路,分别是:浏览器CSS样式初始化、浏览器私有属性,CSS hack语法和自动化插件。

CSS样式初始化

每个浏览器的css默认样式不尽相同,所以最简单有效的方式就是对其进行初始化(覆盖默认样式)

Normalize.css

html {
  line-height: 1.15; /* Correct the line height in all browsers */
  -webkit-text-size-adjust: 100%; /* Prevent adjustments of font size after orientation changes in iOS. */
}
body {
  margin: 0;
}
a {
  background-color: transparent; /* Remove the gray background on active links in IE 10\. */
}
img {
  border-style: none; /*  Remove the border on images inside links in IE 10\. */
}

...

浏览器私有属性

-webkit- ,-moz- ,-ms-等,这是我们经常在某个CSS属性前添加的一些前缀,这些就是浏览器的私有属性。

  • -moz代表firefox浏览器私有属性
  • -ms代表IE浏览器私有属性
  • -webkit代表chrome、safari私有属性
  • -o代表opera私有属性

对于书写顺序一定要注意,兼容性写法放到前面,把标准写法放到最后

-webkit-transform:rotate(-3deg); /*为Chrome/Safari*/
-moz-transform:rotate(-3deg); /*为Firefox*/
-ms-transform:rotate(-3deg); /*为IE*/
-o-transform:rotate(-3deg); /*为Opera*/
transform:rotate(-3deg); 

CSS hack

针对不同的浏览器甚至不同版本编写特定的CSS样式,这一过程就叫做CSS hack

  1. 条件hack:

主要针对IE浏览器进行一些特殊的设置

<!--[if <keywords>? IE <version>?]>

  代码块,可以是html,css,js
    
<![endif]-->

例如:

<!--[if IE]>
  <p>你在非IE中将看不到我</p>
<![endif]-->

<!--[if IE]>
<style>
  .test{color:red;}
</style>
<![endif]-->

<!--[if lt IE 9]>
  <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
  <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->

IE浏览器版本,如6、7、8,但IE10及以上版本已将条件注释特性移除,使用时需注意。

  1. 属性hack:

在CSS样式属性名前加上一些只有特定浏览器才能识别的hack前缀。

selector{<hack>?property:value<hack>?;}

例如:

.test {
  color: #090\9; /* For IE8+ */
  *color: #f00;  /* For IE7 and earlier */
  _color: #ff0;  /* For IE6 and earlier */
}
  1. 选择符级hack:

是针对一些页面表现不一致或者需要特殊对待的浏览器,在CSS选择器前加上一些只有某些特定浏览器才能识别的前缀进行hack。

<hack> selector{ sRules }

例如:

* html .test { color: #090; }       /* For IE6 and earlier */
* + html .test { color: #ff0; }     /* For IE7 */
  1. 自动化插件 Autoprefixer是一款自动管理浏览器前缀的插件,它可以解析CSS文件并且添加浏览器前缀到CSS内容里。
//我们编写的代码
div {
  transform: rotate(30deg);
}
//自动补全的代码,具体补全哪些由要兼容的浏览器版本决定,可以自行设置
div {
  -ms-transform: rotate(30deg);       
  -webkit-transform: rotate(30deg);    
  -o-transform: rotate(30deg);    
  -moz-transform: rotate(30deg);      
  transform: rotate(30deg);
}

css3新属性有哪些

  1. border-color:为边框设置多种颜色
p{
  border-style:solid;  
  border-color:#ff0000 #0000ff #00ffee #eeff00; //上 右 下 左 
}
  1. border-image:图片边框
div{
  -webkit-border-image:url(border.png) 30 30 round; /* Safari 5 */
  -o-border-image:url(border.png) 30 30 round; /* Opera */
  border-image:url(border.png) 30 30 round;
}
  1. border-radius:圆角边框
div{
  border:2px solid;
  border-radius:25px;
}

  1. box-shadow:阴影效果
div{
  box-shadow: 10px 10px [#888888]; // 水平 垂直 [颜色]
  box-shadow: 10px 10px [5px #888888]; // 水平 垂直 [模糊半径 颜色]
  box-shadow: 10px 10px [5px 1px #888888]; // 水平 垂直 [模糊半径 阴影的大小 颜色]
  box-shadow: 10px 10px [5px 1px #888888 inset]; // 水平 垂直 [模糊半径 阴影的大小 颜色 阴影在边框内]
}

例如

div {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: #fff;
  box-shadow:
    0 0 60px 30px #fff,  /* inner white */
    0 0 100px 60px #f0f, /* middle magenta */
    0 0 140px 90px #0ff; /* outer cyan */
}
  1. background-size:指定背景图片尺寸
div{
  background:url(img_flwr.gif);
  background-size:80px 60px;
  background-repeat:no-repeat;
}
  1. background-origin:指定背景图片从哪里开始显示
div{
  background-image:url('smiley.gif');
  background-repeat:no-repeat;
  background-position:left;
  background-origin:content-box; // border-box|padding-box|content-box
}
  1. background-clip:指定背景图片从什么位置开始裁剪
div{
  background-color:yellow;
  background-clip:content-box; // border-box|padding-box|content-box
}
  1. text-shadow:文本阴影
h1{
  text-shadow: 5px 5px [5px #FF0000]; // 水平 垂直 [模糊半径 颜色]
}
  1. word-wrap:自动换行
p{
  word-wrap:break-word;
}
  1. transform:将元素实现旋转、缩放和平移的功能
translate(x,y) // 定义 2D 转换
translate3d(x,y,z) // 定义 3D 转换
translateX(x)
translateY(y)
translateZ(z)

scale(x,y) // 定义 2D 缩放转换
scale3d(x,y,z) // 定义 3D 缩放转换
scaleX(x)
scaleY(y)
scaleZ(z)

rotate(angle) // 定义 2D 旋转,在参数中规定角度
rotate3d(x,y,z,angle) // 定义 3D 旋转
rotateX(angle) 
rotateY(angle) 
rotateZ(angle) 

skew(x-angle,y-angle) // 定义沿着 X 和 Y 轴的 2D 倾斜转换
skewX(angle)
skewY(angle) 

perspective(n) // 为 3D 转换元素定义透视视图
  1. transform-Origin:变换的起点
transform: rotate(45deg);
transform-origin:20% 40% 100px; // X Y Z
  1. transition:过渡效果

:hover、:focus、:active、:checked 等

div{
  width:100px;
  transition: width 2s;
}
div:hover{
  width:300px;
}

怎么理解margin越界的问题

当两个垂直外边距相遇时,它们将形成一个外边距。合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者;而左右外边距不合并。注意:只有普通文档流中块框的垂直外边距才会发生外边距合并。行内框、浮动框或绝对定位之间的外边距不会合并。

解决方案:

  1. 给父元素加边框border
  2. 给父元素设置padding
  3. 父元素添加overflow:hidden
  4. 父元素加前置内容生成
父元素:before{
    content:' ';
    display:table;
}
// 同理margin-bottom也是这样解决的。是给父元素添加最后一个子元素。就可以解决子元素的越界问题。

js的继承方式有哪些

function Animal (name) {
  this.name = name || 'Animal';
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
}
  1. 原型链继承
function Cat() {
}
cat.prototype = new Animal()
cat.prototype.name = "cat"

var cat = new Cat();
console.log(cat.name)
console.log(cat.eat('fish'))
console.log(cat.sleep())
console.log(cat instanceof Animal)  // true
console.log(cat instanceof Cat) // true
  1. 构造继承
function Cat(name){
    Animal.call(this);
    this.name= name || 'Tom';
} 

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal);   //false
console.log(cat instanceof Cat); // true
  1. 实例继承
function Cat(){
  var instance = new Animal();
  instance.name = name || 'Tom';
  return instance;
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
  1. 拷贝继承
function Cat(name){
  var animal = new Animal();
&emsp;// 遍历拷贝属性
  for(var p in animal){
    Cat.prototype[p] = animal[p];
  }
  Cat.prototype.name = name || 'Tom';
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
  1. 组合继承
function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
Cat.prototype = new Animal();

//修复构造函数指向
Cat.prototype.constructor = Cat;


// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
  1. 寄生组合继承
function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
(function(){
  // 创建一个没有实例方法的类
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //将实例作为子类的原型
  Cat.prototype = new Super();
})();

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

Cat.prototype.constructor = Cat; // 需要修复下构造函数
  1. Class 继承
class Cat extends Animal {
  constructor(name){
    super(name);
    this.name= name || 'Animal';
  }
}
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

深拷贝怎么实现

  1. JSON方法实现
let deepClone = function (obj) {
  let _tmp = JSON.stringify(obj); // 将对象转换为json字符串形式
  let result = JSON.parse(_tmp); // 将转换而来的字符串转换为原生js对象
  return result;
};
  1. 递归
function isObject(obj) {
    return typeof obj === 'object' && obj != null;
}

function cloneDeep(source, hash = new WeakMap()) {
  if (!isObject(source)) return source; 
  if (hash.has(source)) return hash.get(source); // 新增代码,查哈希表

  var target = Array.isArray(source) ? [] : {};
  hash.set(source, target); // 新增代码,哈希表设值

  for(var key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      if (isObject(source[key])) {
        target[key] = cloneDeep(source[key], hash); // 新增代码,传入哈希表
      } else {
        target[key] = source[key];
      }
    }
  }
  return target;
}