Front-end interview questions

ES6有哪些新的特性,浏览器的兼容性如何?

let与const 关键字

可以把let看成var,只是它定义的变量被限定在了特定范围内才能使用,而离开这个范围则无效。const则很直观,用来定义常量,即无法被更改值的变量。

for (let i=0;i<2;i++){
  console.log(i);//输出: 0,1
}
cosole.log(i);//输出:undefined,严格模式下会报错
箭头操作符

它简化了函数的书写。操作符左边为输入的参数,而右边则是进行的操作以及返回的值Inputs=>outputs。
我们知道在JS中回调是经常的事,而一般回调又以匿名函数的形式出现,每次都需要写一个function,甚是繁琐。当引入箭头操作符后可以方便地写回调了。请看下面的例子。

var array = [1, 2, 3];
//传统写法
array.forEach(function(v, i, a) {
    console.log(v);
});
//ES6
array.forEach(v = > console.log(v));
for of 值遍历

我们都知道for in 循环用于遍历数组,类数组或对象,ES6中新引入的for of循环功能相似,不同的是每次循环它提供的不是序号而是值。

var someArray = [ "a", "b", "c" ];
for (v of someArray) {
    console.log(v);//输出 a,b,c
}

notice:此功能google traceur并未实现,所以无法模拟调试,

类的支持

ES6中添加了对类的支持,引入了class关键字。JS本身就是面向对象的,ES6中提供的类实际上只是JS原型模式的包装。现在提供原生的class支持后,对象的创建,继承更加直观了,并且父类方法的调用,实例化,静态方法和构造函数等概念都更加形象化。下面代码展示了类在ES6中的使用

//类的定义
class Animal {
    //ES6中新型构造器
    constructor(name) {
        this.name = name;
    }
    //实例方法
    sayName() {
        console.log('My name is '+this.name);
    }
}
//类的继承
class Programmer extends Animal {
    constructor(name) {
        //直接调用父类构造器进行初始化
        super(name);
    }
    program() {
        console.log("I'm coding...");
    }
}
//测试我们的类
var animal=new Animal('dummy'),
wayou=new Programmer('wayou');
animal.sayName();//输出 ‘My name is dummy’
wayou.sayName();//输出 ‘My name is wayou’
wayou.program();//输出 ‘I'm coding...’
增强的对象字面量

对象字面量被增强了,写法更加简洁与灵活,同时在定义对象的时候能够做的事情更多了。具体表现在:
1. 可以在对象字面量里面定义原型
2. 定义方法可以不用function关键字
3. 直接调用父类方法
这样一来,对象字面量与前面提到的类概念更加吻合,在编写面向对象的JavaScript时更加轻松方便了。

//通过对象字面量创建对象
var human = {
    breathe() {
        console.log('breathing...');
    }
};
var worker = {
    __proto__: human, //设置此对象的原型为human,相当于继承human
    company: 'freelancer',
    work() {
        console.log('working...');
    }
};
human.breathe();//输出 ‘breathing...’
//调用继承来的breathe方法
worker.breathe();//输出 ‘breathing...’
字符串模板

ES6中允许使用反引号 ` 来创建字符串,此种方法创建的字符串里面可以包含由美元符号加花括号包裹的变量${vraible}

//产生一个随机数
var num=Math.random();
//将这个数字输出到console
console.log(`your num is ${num}`);
解构

自动解析数组或对象中的值。比如若一个函数要返回多个值,常规的做法是返回一个对象,将每个值做为这个对象的属性返回。但在ES6中,利用解构这一特性,可以直接返回一个数组,然后数组中的值会自动被解析到对应接收该值的变量中。

var [x,y]=getVal(),//函数返回值的解构
    [name,,age]=['wayou','male','secrect'];//数组解构

function getVal() {
    return [ 1, 2 ];
}

console.log('x:'+x+', y:'+y);//输出:x:1, y:2 
console.log('name:'+name+', age:'+age);//输出: name:wayou, age:secrect 

参数默认值,不定参数,拓展参数

默认参数值

现在可以在定义函数的时候指定参数的默认值了,而不用像以前那样通过逻辑或操作符来达到目的了。

function sayHello(name){
    //传统的指定默认参数的方式,默认参数是dude
    var name=name||'dude';
    console.log('Hello '+name);
}
//运用ES6的默认参数
function sayHello2(name='dude'){
    console.log(`Hello ${name}`);
}
sayHello();//输出:Hello dude
sayHello('Wayou');//输出:Hello Wayou
sayHello2();//输出:Hello dude
sayHello2('Wayou');//输出:Hello Wayou
不定参数

不定参数是在函数中使用命名参数同时接收不定数量的未命名参数。这只是一种语法糖,在以前的JavaScript代码中我们可以通过arguments变量来达到这一目的。不定参数的格式是三个句点后跟代表所有不定参数的变量名。比如下面这个例子中,…x代表了所有传入add函数的参数。

//将所有参数相加的函数
function add(...x){
    return x.reduce((m,n)=>m+n); 
    //reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
    //箭头函数等价于function(m,n){return m+n}
}
//传递任意个数的参数
console.log(add(1,2,3));//输出:6
console.log(add(1,2,3,4,5));//输出:15
拓展参数

拓展参数则是另一种形式的语法糖,它允许传递数组或者类数组直接做为函数的参数而不用通过apply

var people=['Wayou','John','Sherlock'];
//sayHello函数本来接收三个单独的参数人一,人二和人三
function sayHello(people1,people2,people3){
    console.log(`Hello ${people1},${people2},${people3}`);
}
//但是我们将一个数组以拓展参数的形式传递,它能很好地映射到每个单独的参数
sayHello(...people);//输出:Hello Wayou,John,Sherlock 

//而在以前,如果需要传递数组当参数,我们需要使用函数的apply方法
sayHello.apply(null,people);//输出:Hello Wayou,John,Sherlock 

ES6浏览器兼容性

即使浏览器对ES6新特性开始渐渐支持,但是这还需要很长一段时间,我们不能百分百依赖浏览器本身对ES6的支持度来开发。虽然出现了各种转换工具,但是到目前为止,还没有一款工具能百分百将ES6的新特性完美地转换成ES5,因为在ES6新增的内容中,存在一些无法在ES5中找到与之匹配的语法,所以不建议在生产环境中使用支持度较低的新特性,后续的教程章节中介绍的新特性前端君也会特意提醒它的兼容性。
解决方法:

使用转换工具babel

用npm安装babel (npm是随同Nodejs一起安装的包管理工具。先安装Nodejs)

npm install babel-core@5

使用babel(电脑盘中找到这样的目录:C:\Users\Administrator\node_modules\babel-core,找到babel的浏览器版本browser.js(未压缩版)和browser.min.js(压缩版)),然后我们将这个文件使用在含有ES6语法的文件中

<script src="browser.min.js"></script>
<script type="text/babel"> //第二个script标签的type为”text/babel”
   const Name = '张三';//使用新增的关键字:const声明常量
   alert(Name);
</script>
  • 大多数使用ES6的项目当然不是把ES6直接放到浏览器里跑,中间是有babel的编译过程的,兼容性的问题只要不是太过于老旧的浏览器都还可以(说句实话,现在PC端的IE8-真的不多了,移动端完全不用担心babel编译的兼容性)

  • 但是 Babel 默认只转换转各种 ES2015 语法,而不转换新的 API,比如 Promise,以及 Object.assign、Array.from 这些新方法,这时我们需要提供一些 ployfill(英译:填充工具) 来模拟出这样一个提供原生支持功能的浏览器环境。

主要有两种方式:babel-runtime 和 babel-polyfill。
  • babel-runtime
    babel-runtime 的作用是模拟 ES2015 环境,包含各种分散的 polyfill 模块,我们可以在自己的模块里单独引入,比如 promise:
import 'babel-runtime/core-js/promise'

它们不会在全局环境添加未实现的方法,只是这样手动引用每个 polyfill 会非常低效,我们可以借助 Runtime transform 插件来自动化处理这一切。

首先使用 npm 安装

npm install babel-plugin-transform-runtime --save-dev

然后在 webpack 配置文件的 babel-loader 增加选项:

loader: ["babel-loader"],
query: {
  plugins: [
    "transform-runtime"
  ],
  presets: ['es2015', 'stage-0']
}
  • babel-polyfill
    而 babel-polyfill 是针对全局环境的,引入它浏览器就好像具备了规范里定义的完整的特性,一旦引入,就会跑一个 babel-polyfill 实例。用法如下:

1.安装 babel-polyfill

npm install babel-polyfill --save

2.在入口文件中引用:

import 'babel-polyfill'

如何区分不同分辨率的设备,并显示对应的内容,pc,平板,微页面?

1.利用@media screen实现网页布局的自适应

(优点:无需插件和手机主题,对移动设备友好,能够适应各种窗口大小。只需在CSS中添加@media screen属性,根据浏览器宽度判断并输出不同的长宽值)

@media screen and (min-width:1200px){}
@media screen and (min-width: 960px) and (max-width: 1199px) {}
@media only screen and (min-width: 480px) and (max-width: 767px){}
@media only screen and (max-width: 479px) {}
2. JS判断访问设备(userAgent)加载不同页面, JS判断客户端操作系统类型(platform)来定义不同的表现
//平台、设备和操作系统  
var system ={  
    win : false,  
    mac : false,  
    xll : false  
}; 
 //检测平台  
    var p = navigator.platform;  
    system.win = p.indexOf("Win") == 0;  
    system.mac = p.indexOf("Mac") == 0;  
    system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);  
    //跳转语句  
    if(system.win||system.mac||system.xll){  
        alert("PC访问");  
    }else{  
        alert("非PC访问");  
    }  

JS判断访问设备(userAgent)加载不同页面。代码如下:

function browserRedirect() {  
    var sUserAgent = navigator.userAgent.toLowerCase();  
    var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";  
    var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";  
    var bIsMidp = sUserAgent.match(/midp/i) == "midp";  
    var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";  
    var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";  
    var bIsAndroid = sUserAgent.match(/android/i) == "android";  
    var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";  
    var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";  
    if (! (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM)) {  
        window.location.href = B页面;  
}}  

JS判断客户端操作系统类型(platform)来定义不同的字体表现。代码如下:

// 更详细的探测当前客户端使用的操作系统  

function detectOS() {  
 var sUserAgent = navigator.userAgent;  
 var isWin = (navigator.platform == "Win32") || (navigator.platform == "Windows");  
 var isMac = (navigator.platform == "Mac68K") || (navigator.platform == "MacPPC") || (navigator.platform == "Macintosh") || (navigator.platform == "MacIntel");          if (isMac)  
 return "Mac";  
var isUnix = (navigator.platform == "X11") && !isWin && !isMac;  
if (isUnix) return "Unix";  
var isLinux = (String(navigator.platform).indexOf("Linux") > -1);  
if (isLinux) return "Linux";  
if (isWin) {  
var isWin2K = sUserAgent.indexOf("Windows NT 5.0") > -1 || sUserAgent.indexOf("Windows 2000") > -1;  
if (isWin2K) return "Win2000";  
var isWinXP = sUserAgent.indexOf("Windows NT 5.1") > -1 || sUserAgent.indexOf("Windows XP") > -1;  
if (isWinXP) return "WinXP";  
var isWin2003 = sUserAgent.indexOf("Windows NT 5.2") > -1 || sUserAgent.indexOf("Windows 2003") > -1;  
17  
if (isWin2003) return "Win2003";  
var isWin2003 = sUserAgent.indexOf("Windows NT 6.0") > -1 || sUserAgent.indexOf("Windows Vista") > -1;  
if (isWin2003) return "WinVista";  
var isWin2003 = sUserAgent.indexOf("Windows NT 6.1") > -1 || sUserAgent.indexOf("Windows 7") > -1;  
if (isWin2003) return "Win7";  
}  
return "other";  
}
3. 根据navigator.userAgent获取用户的浏览器信息,然后用正则匹配判断当前用户的设备是否是手机和pad,如果是的话跳转到另一个页面。
function isMobile() {
    if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))){
       return true;
    }else{
    return false;
    }
}
var urlMobile='/stock/index.html';//手机pad跳转的页面,这个需要开发者自己配置
if(isMobile() !== false)
window.location.href=urlMobile;

这里写图片描述

git的基本操作,遇到冲突如何解决?

git clone 项目地址
git pull origin 分支
git add 文件名
git commit -m '注释'
git push origin 分支
git  branch 分支 //创建本地分支
git branch -D   //删除本地分支
git checkout 分支

如果本地项目和远程服务器的同一文件都有改动,从而发生了冲突。先执行git stash指令,暂存当前的改动状态,再执行git pull指令,就可以成功拉取服务器代码,再执行git stash pop,就可以看到合并后的代码改变。
这里写图片描述
其中上图<<<<<<与=====中的代码为服务器改动的代码,=====与>>>>>>中的代码为本地改动的代码,此时只需要手动处理文件内冲突。然后再commit就不会有报错了。

question:将下面代码所有的span标签的背景变成蓝色

<div id="test">
  <div>
    <span></span>
    <span></span>
    ......
    //好多个span
  </div>
  <span></span>  
</div>

解法1:jquery

$("#test").find('span').css("background","blue");//find() 方法获得当前元素集合中每个元素的后代并进行遍历

解法2:javascript

        var span=document.getElementById('test').getElementsByTagName('span');
        for(var i in span){
            span[i].style.background='blue';
        }

question:取出下面字符串中所有大写的单词

var test="This is A test";
......
结果:[This,A]

split

js原生处理字符串的方法?

JS自带函数

concat

将两个或多个字符的文本组合起来,返回一个新的字符串。

var a = "hello";
var b = ",world";
var c = a.concat(b);
alert(c);
//c = "hello,world"
indexOf

返回字符串中一个子串第一处出现的索引(从左到右搜索)。如果没有匹配项,返回 -1 。

var index1 = a.indexOf("l");
//index1 = 2
var index2 = a.indexOf("l",3);//从第三位开始检索l
//index2 = 3
charAt

返回指定位置的字符。

var get_char = a.charAt(0);
//get_char = "h"
lastIndexOf

返回字符串中一个子串最后一处出现的索引(从右到左搜索),如果没有匹配项,返回 -1 。

var index1 = lastIndexOf('l');
//index1 = 3
var index2 = lastIndexOf('l',2)
//index2 = 2
match

检查一个字符串匹配一个正则表达式内容,如果么有匹配返回 null。

var re = new RegExp(/^\w+$/);
var is_alpha1 = a.match(re);
//is_alpha1 = "hello"
var is_alpha2 = b.match(re);
//is_alpha2 = null
substring

返回字符串的一个子串,传入参数是起始位置和结束位置。

var sub_string1 = a.substring(1);
//sub_string1 = "ello"
var sub_string2 = a.substring(1,4);
//sub_string2 = "ell"
substr

返回字符串的一个子串,传入参数是起始位置和长度

var sub_string1 = a.substr(1);
//sub_string1 = "ello"
var sub_string2 = a.substr(1,4);
//sub_string2 = "ello"
replace

用来查找匹配一个正则表达式的字符串,然后使用新字符串代替匹配的字符串。

var result1 = a.replace(re,"Hello");
//result1 = "Hello"
var result2 = b.replace(re,"Hello");
//result2 = ",world"

执行一个正则表达式匹配查找。如果查找成功,返回字符串中匹配的索引值。否则返回 -1 。

var index1 = a.search(re);
//index1 = 0
var index2 = b.search(re);
//index2 = -1

slice

提取字符串的一部分,并返回一个新字符串(与 substring 相同)。

var sub_string1 = a.slice(1);
//sub_string1 = "ello"
var sub_string2 = a.slice(1,4);
//sub_string2 = "ell"
split

通过将字符串划分成子串,将一个字符串做成一个字符串数组。

var arr1 = a.split("");
//arr1 = [h,e,l,l,o]
length

返回字符串的长度,所谓字符串的长度是指其包含的字符的个数。

var len = a.length();
//len = 5
toLowerCase

将整个字符串转成小写字母。

var lower_string = a.toLowerCase();
//lower_string = "hello"
toUpperCase

将整个字符串转成大写字母。

var upper_string = a.toUpperCase();
//upper_string = "HELLO"

如何处理浏览器兼容性?

less文件如何打包变成可用的css文件的?

webpack提供两个工具处理样式表,css-loader 和 style-loader,

//安装
npm install --save-dev style-loader css-loader
//使用  注意这里对同一个文件引入多个loader的方法。
module.exports = {

   ...
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader"
                    }
                ]
            }
        ]
    }
};

接下来,在app文件夹里创建一个名字为”main.css”的文件,对一些元素设置样式.

/* main.css */
html {
  box-sizing: border-box;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  margin: 0;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

h1, h2, h3, h4, h5, h6, p, ul {
  margin: 0;
  padding: 0;
}

我们这里例子中用到的webpack只有单一的入口,其它的模块需要通过 import, require, url等与入口文件建立其关联,为了让webpack能找到”main.css“文件,我们把它导入”main.js “中,如下

//main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

import './main.css';//使用require导入css文件

render(<Greeter />, document.getElementById('root'));

对小程序了解多少?

  • 它实现了应用「触手可及」的梦想,用户扫一扫或搜一下即可打开应用。也体现了「用完即走」的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。
  • 微信为微信小程序提供了一套基础组件库,可以满足开发的基础开发需求,从而实现简单的快速开发;提供了比较完整的API,能够开发更丰富的功能和程序;还引入新的文件格式。
优点:

用户可便捷地获取服务,不用安装,即开即用,用完就走。省流量,省安装时间,不占用桌面。
可以跨平台(同时支持ios和android),降低开发成本,推广更容易更简单。
体验虽然不能媲美原声app,但综合考虑还是不错的。
启动应用速度快,接近原生APP。

缺点:

不能继承SDK。
不能分享到朋友圈。
开发工具简陋。

javascript为什么是单线程?

JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

对js闭包的了解

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页