前端面试题

2017-07-23  本文已影响0人  杀破狼real

HTML相关

1、XHTML和HTML有什么区别

HTML是一种基本的WEB网页实际语言,XHTML是一种基于XML的置标语言

最主要的不同:

2、什么是语义化的HTML?

3、常见的浏览器内核有哪些?

4、H5有哪些新特性?移除了哪些元素?如何处理HTML5新标签的浏览器兼容问题?

新特性

移除元素

兼容

IE8/IE7/IE6支持通过document.createElement方法产生的标签,可以利用这一特性让这些浏览器支持HTML5新标签。

5、如何实现浏览器内多个标签页之间的通信?

调用 localStroage、cookie 等本地存储方式

6、HTML5为什么只需要写!DOCTYPE HTML?

HTML5 不基于 SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为(让浏览器按照他们应该的方式来运行);而HTML4.0基于SGML,所以需要对DTD进行引用,才能告知浏览器文档所使用的文档类型。

7、Doctype作用?标准模式与兼容模式各有什么区别?

!DOCTYPE声明位于HTML文档中的第一行,处于html标签之前。告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。

标准模式的排版和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。

8、label的作用是什么?怎么用?

label标签是用来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。

用法:

<label for = "Name">Number:</label>
<input type="text" name="Name" id="Name" />

or

<label>Data:<input type="text" name="B" /><label>

CSS相关

1、如何居中div?如何居中一个浮动元素?

//居中div
margin: 0 auto

//居中浮动元素
float:left;
position:relative;
left:50%;

//居中绝对定位div
position:absolute; 
top: 50%; 
left: 50%;
margin:-100px 0px 0px -100

2、经常遇到的浏览器兼容性有哪些?简述原因和解决办法?

1)不同浏览器的标签,默认的margin和padding不同

解决方案:加一个全局的*{margin:0;padding:0;}来统一。

2)IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。

解决方案:在float的标签样式控制中加入 display:inline;将其转化为行内属性。

3)在IE6,IE7中元素高度超出自己设置高度。

原因:IE8以前的浏览器中会给元素设置默认的行高的高度导致的。

解决方案:加上overflow:hidden或设置line-height为更小的高度。

4)min-height在IE6下不起作用

解决方案:添加 height:auto !important;height:xxpx;其中xx就是min-height设置的值。

5)a(有href属性)标签嵌套下的img标签,在IE下会带有边框

解决方案:加上a img{border:none;}样式。

6)IE6下border:none无效

解决方案:用:border:0或border:0 none;或border:none:border-color:transparent;,推荐用第三种方案。

3、CSS3的新特性

4、CSS优化、提高性能的方法有哪些?

5、简要说说CSS的元素分类?

6、CSS清除浮动的几种方法

7、display有哪些值?说明他们的作用。

8、position的值, relative和absolute分别是相对于谁进行定位的?

9、CSS引入的方式有哪些? link和@import的区别是?

内联 内嵌 外链 导入

区别:同时加载

前者无兼容性,后者CSS2.1以下浏览器不支持
Link 支持使用javascript改变样式,后者不可

10、CSS选择器 ~ 和 + 有什么区别?

~ 匹配所有兄弟元素,+ 匹配紧挨着的兄弟元素。

另外:> 匹配所有子元素,(空格) 匹配所有后代元素。

11、CSS中的常见单位?

JS相关

1、谈一谈JavaScript作用域链

当执行一段 JavaScript 代码(全局代码或函数)时,JavaScript 引擎会为其创建一个作用域(又称为执行上下文),在页面加载后会首先创建一个全局作用域,然后每执行一个函数,会建立一个对应的作用域,从而形成一条作用域链。每个作用域都有一条对应的作用域链,链头是全局作用域,链尾是当前函数作用域。

作用域链的作用是用于解析标识符,当函数被创建时(不是被执行),会将this、arguments、命名参数和该函数中所有局部变量添加到当前作用域中。当JavaScript需要查找变量x的时候(这个过程被称为解析),它首先会从作用域链中的链尾(也就是当前作用域)进行查找是否有x属性,如果没有找到就顺着作用域链继续查找,直到查找到链头(也就是全局作用域链),仍未找到该变量的话,就认为这段代码的作用域链上不存在x变量,并抛出一个引用错误的异常。

2、原型是什么?原型链是什么?

JavaScript中的每个对象都有一个prototype属性,我们称之为原型,而原型的值也是一个对象,因此它也有自己的原型,这样就串联起来了一条原型链,原型链的链头是object,它的prototype比较特殊,值为null。

原型链的作用是用于对象继承,函数A的原型属性(prototype property)是一个对象,当这个函数被用作构造函数来创建实例时,该函数的原型将被作为原型赋值给所有实例对象,比如我们创建一个数组,数组的方法便从数组的原型上继承而来。

原型五项规则

3、构造函数,原型对象,实例对象三者之间的关系

每创建一个函数,该函数都会自动带有一个prototype属性。该属性是一个指针,指向一个对象,该对象称之为原型对象。

原型对象上默认有一个属性constructor,该属性也有一个指针,指向其关联的构造函数。

通过调用构造函数产生的实例对象,都拥有一个内部属性,指向了原型对象。其实例对象能够访问原型对象上的所有对象和方法。

总结:三者的关系是,每个构造函数都有一个原型对象,原型对象上包含着一个指向构造函数的指针,而实例都包含着一个指向原型对象的内部指针。通俗的讲,实例可以通过内部指针访问到原型对象,原型对象可以通过constructor找到构造函数。

4、什么是闭包?闭包的作用?

闭包就是函数中的函数,里面的函数可以访问外面函数的变量,外面的变量是这个内部函数的一部分。

闭包就是函数能够记住并访问它的词法作用域,即使当这个函数在它的词法作用域之外执行时。

闭包作用

闭包使用场景

闭包不能滥用,否则会导致内存泄漏,影响网页的性能。闭包使用完成后,要立即释放资源,将引用变量指向 null 。

4、JSON是什么

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它是基于 JavaScript 的一个子集。数据格式简单,易于读写,占用宽带小。是前后台交互最常见的一种数据格式。JSON也只不过就是一个js对象而已

常用方法

JSON.stringify({name: 'xiaoxin', age: 20}) //对象转为字符串
JSON.parse('{name: \'xiaoxin\', age: 20}') //字符串转为对象

5、JavaScript有几种类型的值?区别是什么?

两大类

区别

原始数据类型 直接存储在栈(stack)中的简单数据段,占用空间小、大小固定,属于被频繁使用数据。

引用数据类型 存储在堆(heap)中的对象,占用空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,首先会检索其在栈中的地址,然后从堆中获取实体。

6、谈谈对this的理解?

this 表示当前对象,this 的指向是根据调用的上下文来决定的,默认指向 window 对象,指向 window 对象时可以省略不写,例如

this.alert() === window.this.alert() === alert()

,调用的上下文环境包括全局和局部。

执行时才能确认值,定义时无法确认

全局环境 就是在<script></script>中,这里的 this 始终指向的是 window 对象;

局部环境

7、同步和异步的区别?

同步是一种线性执行的方式,执行的流程不能跨越。一般用于流程性比较强的程序,比如用户登录;

异步是一种并行处理的方式,不必等待一个程序执行完,就可以执行其它任务。在程序中异步处理的结果通常使用回调函数来处理结果。在 JavaScript 中实现异步的方式一般是 Ajax 和 H5 新增的 Web Worker

何时需要异步?

因此,所有的“等待的情况”都需要异步

前端使用异步的场景?

8、call和apply的区别?

相同点 两个方法产生的作用是一样的,都用来改变当前函数调用的对象;

不同点 调用的参数不同,

foo.call(this, arg1, arg2, arg3) == foo.apply(this, args) == this.foo(arg1, arg2, arg3)

9、eval是做什么的?

把字符串参数解析成JS代码运行,并返回执行的结果。

10、new操作符干了什么?

11、造成JS内存泄漏的情况?

12、写出下列结果?

console.log(null == NaN); //false
console.log(null == undefined); //true
console.log(null == false); //false
console.log(false == ''); //true
console.log(false == 0); //true
console.log(2 + 1 + '3'); //33
console.log('2' + 1 + 3); //213
console.log(Number(undefined)); //NaN
console.log(Number(NaN)); //NaN
console.log(Number(null)); //0
console.log(Number('')); //0
console.log(Number('123')); //123
console.log(isNaN(23)); //false
console.log(isNaN(NaN)); //true
console.log(isNaN(undefined));//true
console.log(isNaN(null)); //false
console.log(typeof NaN); //number
console.log(typeof '123'); //string
console.log(typeof undefined); //undefined
console.log(typeof 123); //number
console.log(typeof null); //object
console.log(typeof []); //object
console.log(typeof Array); //function
console.log(typeof console.log); //function
console.log(NaN == NaN); //false
console.log(undefined == undefined); //true

13、JS绑定事件的方法?

1)在DOM上直接绑定

<input type="button" value="click me" onclick="hello()" />
 
<script>
function hello(){
    alert('hello')
}
</script>

2)在JavaScript代码中绑定事件

<input type="button" value="click me" id="btn">
 
<script>
document.getElementById('btn').onclick = function(){
    alert('hello');
}
</script>

3)使用事件监听绑定

W3C标准语法:

element.addEventListener(event, function, useCapture)

<input type="button" value="click me" id="btn">
 
<script>
document
    .getElementById('btn')
    .addEventListener('click', function() {
        alert('hello);
    })
</script>

IE标准语法:

element.attachEvent(event, function)

14、JavaScript事件流机制?

1)冒泡型机制

事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发

2)捕获型机制

事件从最不精确的对象(document对象)开始触发,然后到最精确。

3)DOM事件流

同时支持两种事件模型:捕获型事件和冒泡型事件,但是捕获型事件先发生。两种事件都会触发DOM中的所有对象,从document对象开始,也在document对象结束。

事件捕获机制:事件从最上一级标签开始往下查找,直到捕获到事件目标;

事件冒泡机制:事件从事件目标开始,往上冒泡直到页面的最上一级标签。

事件的传播是可以阻止的:

在捕获的事件中stopPropagation()后,后面的冒泡过程也不会发生了

阻止事件的默认行为:

不是所有事件都能冒泡,例如:blur、focus、load、unload等

普通事件和事件绑定的区别?

普通事件的方法不支持添加多个,最下面的事件会覆盖上面的;事件绑定可以添加多个

15、JavaScript实现继承的几种方式?

//父类
function Animal(name) {
  this.name = name || 'Animal';

  this.sleep = function () {
    console.log(this.name + ' sleep');
  };
}
Animal.prototype.eat = function (food) {
  console.log(this.name + ' eating ' + food)
};

//原型链继承
function Cat() {
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';

//构造继承(不能继承原型方法)
function Cat(name) {
  Animal.call(this);
  this.name = name || 'Tom';
}

//实例继承
function Cat(name) {
  const instance = new Animal();
  instance.name = name || 'Tom';
  return instance;
}

//拷贝继承
function Cat(name) {
  const animal = new Animal();
  for (let p in animal) {
    Cat.prototype[p] = animal[p];
  }
  Cat.prototype.name = name || 'Tom';
}

16、简要说明对模块化开发的理解?

所谓模块化开发就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能。模块化开发的基础就是函数。

17、Ajax的工作原理?写一个Ajax请求?

Ajax的工作原理相当于在用户和服务器之间加了一个中间件(Ajax引擎),是用户操作与浏览器响应异步化。

const xhr = new XMLHttpRequest();
xhr.open('get', '/api', false);
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) { // 0 请求未初始化 1 请求已建立 2 请求已发送 3 请求处理中 4 响应已完成
        if (xhr.status == 200) { // 2xx 请求成功 3xx 请求重定向 4xx 客户端错误 5xx 服务端错误
            console.log(xhr.responseText)
        }
    }
};
xhr.send(null);

18、写出两种单例模式的实现?

//自变量
const singleton = {
    attr: 1,
    method: function () {
        return this.attr;
    }
};

//构造函数内部判断
function Construct() {
    if(Construct.unique !== undefined){
        return Construct.unique;
    }
    this.name = 'name';
    this.age = 24;
    Construct.unique = this;
}

19、ES6中Array.isArray的代码实现?

Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) == '[object Array]';
}

20、window.onload 和 DOMContentLoaded 区别

21、随机打印1-100间的10个数字,去重后取出该10个数字之间的最大值和最小值。

function randomMaxMin() {
  const numbers = [...new Set([...new Array(10)].reduce(origin => {
    origin.push(Math.ceil(Math.random() * 100));
    return origin;
  }, []))].sort((a, b) => a - b);
  return {min: numbers[0], max: numbers[numbers.length - 1]};
}

22、写一个长度一致的随机数

let random = Math.random() + '0000000000';
random = random.slice(0, 10);

23、写一个能遍历数组和对象的forEach函数

function forEach(obj, fn) {
  if (obj instanceof Array) {
    obj.forEach((item, index) => fn(index, item));
  } else {
    Object.keys(obj).forEach(key => fn(key, obj[key]));
  }
}
forEach({name: 'pp', age: 20}, (key, value) => {});
forEach([1,2,3], (index, item) => {});

24、写一个闭包的使用场景

function isFirstLoad() {
  const _list = [];
  return function (id) {
    if(_list.indexOf(id) >= 0){
      return false;
    }else{
      _list.push(id);
      return true;
    }
  };
}
const firstLoad = isFirstLoad();
console.log(firstLoad(10)); //true
console.log(firstLoad(10)); //false
console.log(firstLoad(20)); //true
console.log(firstLoad(20)); //false

25、动态创建10个标签,点击弹出对应的序号

for (var i = 0; i < 10; i++) {
  (function (i) {
    var a = document.createElement('a');
    a.innerHTML = 'aaa' + (i + 1) + '</br>';
    a.addEventListener('click', function (e) {
      e.preventDefault();
      alert(i + 1);
    });
    document.body.appendChild(a);
  })(i);
}

最简单的方式用 let 替换 var 进行定义。

26、写一个原型继承的案例

function Elem(id) {
  this.elem = document.getElementById(id);
}
Elem.prototype.html = function (val) {
  const elem = this.elem;
  if(val){
    elem.innerHTML = val;
    return this;
  }else{
    return elem.innerHTML;
  }
};
Elem.prototype.on = function (type, fun) {
  const elem = this.elem;
  elem.addEventListener(type, fun);
  return this;
};

//exec
const div1 = new Elem('app');
div1.html('<p>Hello</p>').on('click', function () {
  alert('hello');
}).html('<p>peter</p>');

27、编写一个通用的事件监听函数?

function bindEvent(elem, type, selector, fn) {
  if (fn == null) {
    fn = selector;
    selector = null;
  }
  elem.addEventListener(type, function (e) {
    if (selector) {
      //代理
      const target = e.target;
      if (target.matches(selector)) {
        fn.call(target, e);
      }
    } else {
      //不是代理
      fn(e);
    }
  });
}

const div1 = document.getElementById('div1');
bindEvent(div1, 'click', 'a', function (e) {
  e.preventDefault();
  console.log(this.innerHTML);
});

const p1 = document.getElementById('p1');
bindEvent(p1, 'click', function () {
  console.log(p1.innerHTML);
});

28、js写一个冒泡排序算法

//冒泡排序
function bubble() {
  const arr = [3, 1, 2, 4];
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  console.log(arr);
}
bubble(); //[1, 2, 3, 4]

29、JS写一个选择排序算法

//选择算法
function selection() {
  const arr = [3, 1, 2, 4];
  for (let i = 0; i < arr.length - 1; i++) {
    let min = i;
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[min]) {
        min = j;
      }
    }
    [arr[i], arr[min]] = [arr[min], arr[i]];
  }
  console.log(arr);
}
selection(); //[1, 2, 3, 4]

30、JS写一个插入排序算法


//插入排序
function insertion() {
  const arr = [3, 1, 2, 4];
  for (let i = 1; i < arr.length; i++) {
    for (let j = i - 1; j >= 0; j--) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }  
  console.log(arr);
}
insertion(); //[1, 2, 3, 4]

31、写一个二分法的函数,返回给定值的索引

//二分法找索引
function dichotomy(arr, val) {
  let start = 0, end = arr.length - 1;
  while (start < end) {
    let middle = end == 1 ? 0 : Math.floor((start + end + 1) / 2);
    if (arr[middle] > val) {
      end = middle;
    } else if (arr[middle] < val) {
      start = middle;
    } else {
      return middle;
    }
  }
  return -1;
}
console.log(dichotomy([2,3,4,5], 3)); //1

32、现有一个URL字符串“http://www.xxx.com?pn=0”,请写出删除其中的pn属性的js代码,请尽量实现完整,考虑全面。

const arr = url.split('?');
const new_url = arr[0] + '?' + arr[1].split('&')
    .reduce((origin, item) => {
      (item.split('=')[0] != 'pn') && origin.push(item);
      return origin;
    }, []).join('&');
console.log(new_url); //http://www.xxx.com

33、写一个函数,计算100以内的质数(只能被1或本身整除的数)。

const calcPrimeNumbers = sum => (
  [...new Array(sum)].reduce((origin, item, index) => {
    const [number, arr] = [++index, []];
    for (let i = 1; i <= number; i++) {
      number % i == 0 && arr.push(i);
    }
    arr.length == 2 && origin.push(number);
    return origin;
  }, [])
);
console.log(calcPrimeNumbers(100)); //[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 ]

34、用 JS 实现一个无限累加的函数 add

function add() {
  let sum = [...arguments].reduce((a, b) => a + b);

  const foo = function () {
    sum += [...arguments].reduce((a, b) => a + b);
    return foo;
  };

  foo.toString = () => sum;

  return foo;
}
console.log(add(1)(2)(3)(4)); // 10
console.log(add(1,1)(2,2)(3,3)(4,4)); // 20

35、手动实现一个sleep函数?

function sleep(time) {
  const start = Date.now();
  while (true) {
    if(Date.now() - time > start)
    break;
  }
  console.log('休息了' + time / 1000 + '秒')
}

sleep(3000); //休息了3秒

36、普通函数和箭头函数的区别?

37、如何发送携带cookie的跨域请求?

设置 withCredentials = true;

38、根据id快速查找对应的元素

const tree = {
  id: 'root',
  children: [
    { id: 1, children: [] },
    { id: 2, children: [] },
    { id: 3, children: [] },
    {
      id: 4,
      children: [
        { id: 5, children: [] },
      ]
    },
  ]
};

function find(id, node = tree) {
  if (node.id == id) {
    return node.children;
  }

  let target;
  node.children.forEach(child => {
    if (child.id == id) {
      target = child.children;
    } else {
      find(child.id, child);
    }
  });
  return target;
}

console.log(find(1)); // []

39、实现对数组进行乱序

var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

var sign = 1;

arr.sort((a, b) => {
  sign = Math.random() > 0.5 ? 1 : -1;
  return (a - b) * sign;
});

console.log(arr);

40、计算长度为100的数组前10个元素之和。

var arr = [...new Array(100)].map((item, i) => i + 1);
var result = arr.slice(0, 10).reduce((pre, current) => pre + current);
console.log(result); // 55

41、手动实现一个bind函数

Function.prototype.myBind = function (oThis) {
  let args = [...arguments].slice(1);
  const context = this;
  const bound = function () {
    args = [...args, ...arguments];
    return context.apply(this instanceof F && oThis ? this : oThis, args);
  };
  const F = function () {
  };
  F.prototype = context.prototype;
  bound.prototype = new F();
  return bound;
};

function read(name, time, book) {
  console.log(`${name} is reading ${book} at ${time}`)
}

const tomRead = read.myBind(this, 'Tom', 'morning');
tomRead('三体'); // Tom is reading 三体 at morning

42、手动实现一个深拷贝

function copy(obj) {
  const result = obj instanceof Array ? [] : {};
  for (let item in obj) {
    if (typeof obj[item] == 'object') {
      result[item] = copy(obj[item]);
    } else {
      result[item] = obj[item];
    }
  }
  return result;
}

6、HTTP状态码分别表示什么?

2xx 成功

3xx 重定向

4xx 客户端错误

5xx 服务端错误

details

上一篇 下一篇

猜你喜欢

热点阅读