前端面试题(JavaScript)

JavaScript

1,介绍js的基本数据类型。

Undefined、Null、Boolean、Number、String

2,介绍js有哪些内置对象?
ObjectJavaScript 中所有对象的父对象
数据封装类对象:Object、Array、Boolean、Number 和 String
其他对象:Function、Arguments、Math、Date、RegExp、Error

3,JavaScript原型,原型链 ? 有什么特点?
每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念。
关系:instance.constructor.prototype = instance.__proto__
特点:
JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。

4,JavaScript有几种类型的值?
:原始数据类型(Undefined,Null,Boolean,Number、String
:引用数据类型(对象、数组和函数)
两种类型的区别是:存储位置不同
1,原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
2,引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体

5,JavaScript继承的几种实现方式?
1,构造函数继承,使用callapply两个方法的特性可以实现,改变方法中的this
2,原型链继承
3,组合式继承

6,javascript创建对象的几种方式?
javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON;但写法有很多种,也能混合使用。

  • 对象字面量的方式 person{firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
  • function来模拟无参的构造函数
function Person(){} 
    var person=new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class 
    person.name=“Mark"; 
    person.age="25"; 
    person.work=function(){ 
    alert(person.name+" hello..."); 
} 
person.work();
  • 用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性)
function Pet(name,age,hobby){ 
   this.name=name;//this作用域:当前对象 
   this.age=age; 
   this.hobby=hobby; 
   this.eat=function(){ 
      alert("我叫"+this.name+",我喜欢"+this.hobby+",是个程序员"); 
   } 
} 
var maidou =new Pet("麦兜",25,"coding");//实例化、创建对象 
maidou.eat();//调用eat方法
  • 用工厂方式来创建(内置对象)
var wcDog =new Object(); 
wcDog.name="旺财"; 
wcDog.age=3; 
wcDog.work=function(){ 
  alert("我是"+wcDog.name+",汪汪汪......"); 
} 
wcDog.work(); 
  • 用原型方式来创建
function Dog(){ } 
Dog.prototype.name="旺财"; 
Dog.prototype.eat=function(){alert(this.name+"是个吃货");} 
var wangcai =new Dog(); 
wangcai.eat(); 
  • 用混合方式来创建
function Car(name,price){ 
   this.name=name; 
   this.price=price; 
} 
Car.prototype.sell=function(){ 
   alert("我是"+this.name+",我现在卖"+this.price+"万元"); 
} 
var camry =new Car("凯美瑞",27); 
camry.sell();

7,Javascript作用链域?
全局作用域指的是window
局部作用域指的是每一个函数内部,在作用域中查找一个变量首先在自己当前作用域查找找不到向上级查找,逐层向上找到window为止,找不到就会抛出一个错误,这个查找的过程就叫作用域链,作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的
作用域链有一个需要要注意的问题就是变量提升,当一个变量的使用在定义之前的时候就会得到一个undefined值,在es6中则不会出现这个问题,es6不允许在定义之前使用

8,谈谈This对象的理解。
functionthis指的的是window
如果是实用new 调用的话this指的是当前的实例化对象
在事件调用函数中this指的调用事件的window
特殊的是在IE中的attachEvent中的this总是指向全局对象Window
在定时器中this指的是window
在es6中有一个箭头函数,在箭头函数中this永远指向的是父级对象

9,什么是window对象? 什么是document对象?
window:它是一个顶层对象,而不是另一个对象的属性,即浏览器的窗口。
document:代表整个HTML 文档,可用来访问页面中的所有元素
Window 对象表示当前浏览器的窗口,是JavaScript的顶级对象。我们创建的所有对象、函数、变量都是 Window 对象的成员
Window 对象的方法和属性是在全局范围内有效的。
Document 对象是 HTML 文档的根节点与所有其他节点(元素节点,文本节点,属性节点, 注释节点)
Document 对象使我们可以通过脚本对 HTML 页面中的所有元素进行访问
Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问

10,null,undefined 的区别?
null 表示一个对象被定义了,值为“空值”;
undefined 表示不存在这个值。

typeof undefined //“undefined”
undefined :是一个表示"无"的原始值或者说表示"缺少值",就是此处应该有一个值,但是还没有定义。当尝试读取时会返回 undefined;
例如变量被声明了,但没有赋值时,就等于undefined

typeof null //“object”
null : 是一个对象(空对象, 没有任何属性和方法);
例如作为函数的参数,表示该函数的参数不是对象;

注意:
在验证null时,一定要使用 === ,因为 == 无法分别 nullundefined
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
1)变量被声明了,但没有赋值时,就等于undefined
2) 调用函数时,应该提供的参数没有提供,该参数等于undefined
3)对象没有赋值的属性,该属性的值为undefined
4)函数没有返回值时,默认返回undefined

null表示"没有对象",即该处不应该有值。典型用法是:
1) 作为函数的参数,表示该函数的参数不是对象。
2) 作为对象原型链的终点。

11,事件是?IE与火狐的事件机制有什么区别? 如何阻止冒泡?

  • 我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为。
  • 事件处理机制:IE是事件冒泡、Firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件;
  • ev.stopPropagation();(旧IE的方法 ev.cancelBubble = true;)

12,什么是闭包(closure),为什么要用它?
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。
闭包的特性
1,函数内再嵌套函数
2,内部函数可以引用外层的参数和变量
3,参数和变量不会被垃圾回收机制回收
闭包的使用场景
常见的闭包的使用场景就是模块化,用来做模块内部的实现通过接口的扩展贡其他模块使用
在就是闭包可以用来缓存值,减少不必要的技术,例如vue里面的计算属性

13、如何判断一个对象是否属于某个类?

if(a instanceof Person){ alert('yes’); }

14、Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?

hasOwnProperty
javaScripthasOwnProperty函数方法是返回一个布尔值,指出一个对象是否具有指定名称的属性。此方法无法检查该对象的原型链中是否具有该属性;该属性必须是对象本身的一个成员。

使用方法:

object.hasOwnProperty(proName)

其中参数object是必选项。一个对象的实例。
proName是必选项。一个属性名称的字符串值。

如果 object 具有指定名称的属性,那么JavaScripthasOwnProperty函数方法返回 true,反之则返回 false

15、JSON 的了解?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小
JSON字符串转换为JSON对象:

var obj =eval('('+ str +')');
var obj = str.parseJSON();
var obj = JSON.parse(str);

JSON对象转换为JSON字符串:

var last=obj.toJSONString();
var last=JSON.stringify(obj);

16、documen.write和 innerHTML的区别
document.write只能重绘整个页面
innerHTML可以重绘页面的一部分

17、DOM操作——怎样添加、移除、移动、复制、创建和查找节点?
1)创建新节点

createDocumentFragment()    //创建一个DOM片段 
createElement()   //创建一个具体的元素 
createTextNode()   //创建一个文本节点 

2)添加、移除、替换、插入

appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点

3)查找

getElementsByTagName()    //通过标签名称 
getElementsByName()    //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的) 
getElementById()    //通过元素Id,唯一性

18、那些操作会造成内存泄漏?

  • 使用闭包的时候如果在闭包变量中保存了大量的dom结构而且不去使用长期存在的时候
  • 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在
  • 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。
  • setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏
  • 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

19、是否了解公钥加密和私钥加密
一般情况下是指私钥用于对数据进行签名,公钥用于对签名进行验证;
HTTP网站在浏览器端用公钥加密敏感数据,然后在服务器端再用私钥解密。

20、attribute和property的区别是什么?
attributedom元素在文档中作为html标签拥有的属性;
property就是dom元素在js中作为对象拥有的属性。

21、描述浏览器的渲染过程,DOM树和渲染树的区别?
浏览器的渲染过程

解析HTML构建 DOM(DOM树),并行请求 css/image/js
CSS 文件下载完成,开始构建 CSSOM(CSS树)
CSSOM 构建结束后,和 DOM 一起生成 Render Tree(渲染树)
布局(Layout):计算出每个节点在屏幕中的位置
显示(Painting):通过显卡把页面画到屏幕上
DOM树 和 渲染树 的区别:
DOM树与HTML标签一一对应,包括head和隐藏元素
渲染树不包括head和隐藏元素,大段文本的每一个行都是独立节点,每一个节点都有对应的css属性

22、介绍DOM0,DOM2,DOM3事件处理方式区别
DOM0级事件处理方式:

 btn.onclick = func;
 btn.onclick = null;

DOM2级事件处理方式:

btn.addEventListener('click', func, false);
btn.removeEventListener('click', func, false);
btn.attachEvent("onclick", func);
btn.detachEvent("onclick", func);

DOM3级事件处理方式:

eventUtil.addListener(input, "textInput", func);

eventUtil 是自定义对象,textInput 是DOM3级事件

23、阻止冒泡和阻止捕获的方法
阻止冒泡
• 在W3c中,使用stopPropagation()方法
• 在IE下设置cancelBubble = true;
在捕获的过程中stopPropagation();后,后面的冒泡过程也不会发生了。
阻止捕获

阻止事件的默认行为,例如click <a>后的跳转
• 在W3c中,使用preventDefault()方法;
• 在IE下设置window.event.returnValue = false;

24、什么是函数节流?介绍一下应用场景和原理?
函数节流(throttle)是指阻止一个函数在很短时间间隔内连续调用。 只有当上一次函数执行后达到规定的时间间隔,才能进行下一次调用。 但要保证一个累计最小调用间隔(否则拖拽类的节流都将无连续效果)

函数节流用于 onresize, onscroll 等短时间内会多次触发的事件

函数节流的原理:使用定时器做时间节流。 当触发一个事件时,先用 setTimout 让这个事件延迟一小段时间再执行。 如果在这个时间间隔内又触发了事件,就 clearTimeout 原来的定时器, 再 setTimeout 一个新的定时器重复以上流程。

函数节流简单实现

function throttle(method, context) {
   clearTimeout(methor.tId);
   method.tId = setTimeout(function(){
       method.call(context);
   }, 100); // 两次调用至少间隔 100ms
}
// 调用
window.onresize = function(){
  throttle(myFunc, window);
}

25、new 操作符具体干了什么?
创建实例对象,this 变量引用该对象,同时还继承了构造函数的原型
属性和方法被加入到 this 引用的对象中
新创建的对象由 this 所引用,并且最后隐式的返回 this

26、JavaScript实现异步编程的方法?
回调函数
事件监听
发布/订阅
Promises对象
Async函数[ES7]

27、常见的几种数组排序算法JS实现

  • 快速排序
    从给定的数据中,随机抽出一项,这项的左边放所有比它小的,右边放比它大的,然后再分别这两边执行上述操作,采用的是递归的思想,总结出来就是 实现一层,分别给两边递归,设置好出口
function fastSort(array,head,tail){
    //考虑到给每个分区操作的时候都是在原有的数组中进行操作的,所以这里head,tail来确定分片的位置
    /*生成随机项*/
    var randomnum = Math.floor(ranDom(head,tail));
    var random = array[randomnum];
    /*将小于random的项放置在其左边  策略就是通过一个临时的数组来储存分好区的结果,再到原数组中替换*/
    var arrayTemp = [];
    var unshiftHead = 0;
    for(var i = head;i <= tail;i++){
      if(array[i]<random){
        arrayTemp.unshift(array[i]);
        unshiftHead++;
      }else if(array[i]>random){
        arrayTemp.push(array[i]);
      }
      /*当它等于的时候放哪,这里我想选择放到队列的前面,也就是从unshift后的第一个位置放置*/
      if(array[i]===random){
        arrayTemp.splice(unshiftHead,0,array[i]);
      }
    }
    /*将对应项覆盖原来的记录*/
    for(var j = head , u=0;j <= tail;j++,u++){
      array.splice(j,1,arrayTemp[u]);
    }
    /*寻找中间项所在的index*/
    var nowIndex = array.indexOf(random);

    /*设置出口,当要放进去的片段只有2项的时候就可以收工了*/
    if(arrayTemp.length <= 2){
      return;
    }
    /*递归,同时应用其左右两个区域*/
    fastSort(array,head,nowIndex);
    fastSort(array,nowIndex+1,tail);
}
  • 插入排序
    思想就是在已经排好序的数组中插入到相应的位置,以从小到大排序为例,扫描已经排好序的片段的每一项,如大于,则继续往后,直到他小于一项时,将其插入到这项的前面
function insertSort(array){
    /*start根据已排列好的项数决定*/
    var start=1;
    /*按顺序,每一项检查已排列好的序列*/
    for(var i=start; i<array.length; start++,i++){
      /*跟已排好序的序列做对比,并插入到合适的位置*/
      for(var j=0; j<start; j++){
        /*小于或者等于时(我们是升序)插入到该项前面*/
        if(array[i]<=array[j]){
          console.log(array[i]+' '+array[j]);
          array.splice(j,0,array[i]);
          /*删除原有项*/
          array.splice(i+1,1);
          break;
        }
      }
    }
}
  • 冒泡排序
    故名思意 ,就是一个个冒泡到最前端或者最后端,主要是通过两两依次比较,以升序为例,如果前一项比后一项大则交换顺序,一直比到最后一对
function bubbleSort(array){
    /*给每个未确定的位置做循环*/
    for(var unfix=array.length-1; unfix>0; unfix--){
      /*给进度做个记录,比到未确定位置*/
      for(var i=0; i<unfix;i++){
        if(array[i]>array[i+1]){
          var temp = array[i];
          array.splice(i,1,array[i+1]);
          array.splice(i+1,1,temp);
        }
      }
    }
  }
  • 选择排序
    将当前未确定块的min或者max取出来插到最前面或者后面
function selectSort(array){
    /*给每个插入后的未确定的范围循环,初始是从0开始*/
    for(var unfixed=0; unfixed<array.length; unfixed++){
      /*设置当前范围的最小值和其索引*/
      var min = array[unfixed];
      var minIndex = unfixed;
      /*在该范围内选出最小值*/
      for(var j=unfixed+1; j<array.length; j++){
        if(min>array[j]){
          min = array[j];
          minIndex = j;
        }
      }
      /*将最小值插入到unfixed,并且把它所在的原有项替换成*/
      array.splice(unfixed,0,min);
      array.splice(minIndex+1,1);
    }
  }

28、svn与git的区别
git是分布式的,svn不是。
git跟svn一样有自己的集中式版本库或服务器。但git更倾向于被使用于分布式模式,克隆版本库后即使没有网络也能够commit文件,查看历史版本记录,创建项目分支等,等网络再次连接上Push到服务器端。

git把内容按元数据方式存储,而svn是按文件。
所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。
git目录是处于你的机器上的一个克隆版的版本库,它拥有中心版本库上所有的东西,例如标签,分支,版本记录等。

git没有一个全局的版本号,svn有。

git的内容完整性优于svn。
因为git的内容存储使用的是SHA-1哈希算法。

git可以有无限个版本库,svn只能有一个指定中央版本库。
当svn中央版本库有问题时,所有工作成员都一起瘫痪直到版本库维修完毕或者新的版本库设立完成。
每一个git都是一个版本库,区别是它们是否拥有活跃目录(Git Working Tree)。如果主要版本库(例如:置於GitHub的版本库)有问题,工作成员仍然可以在自己的本地版本库(local repository)提交,等待主要版本库恢复即可。工作成员也可以提交到其他的版本库!

29、图片懒加载与预加载
图片懒加载的原理就是暂时不设置图片的src属性,而是将图片的url隐藏起来,比如先写在data-src里面,等某些事件触发的时候(比如滚动到底部,点击加载图片)再将图片真实的url放进src属性里面,从而实现图片的延迟加载
图片预加载是指在一些需要展示大量图片的网站,实现图片的提前加载。从而提升用户体验。常用的方式有两种,一种是隐藏在cssbackgroundurl属性里面,一种是通过javascriptImage对象设置实例对象的src属性实现图片的预加载。相关代码如下:

CSS预加载图片方式:

#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }  
#preload-02 { background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }  
#preload-03 { background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
Javascript预加载图片的方式:
function preloadImg(url) {
    var img = new Image();
    img.src = url;
    if(img.complete) {
        //接下来可以使用图片了
        //do something here
    } else {
        img.onload = function() {
            //接下来可以使用图片了
            //do something here
        };
    }
}

30、浅拷贝vs深拷贝
拷贝其实就是对象复制,为了解决对象复制是产生的引用类型问题
浅拷贝:利用迭代器,循环对象将对象中的所有可枚举属性复制到另一个对象上,但是浅拷贝的有一个问题就是只是拷贝了对象的一级,其他级还如果是引用类型的值的话依旧解决不了
深拷贝:深拷贝解决了浅拷贝的问题,利用递归的形势便利对象的每一级,实现起来较为复杂,得判断值是数组还是对象;

31、区分数组和对象的方法?

  • 从原型入手,Array.prototype.isPrototypeOf(obj);
    利用isPrototypeOf()方法,判定Array是不是在obj的原型链中,如果是,则返回true,否则false。
Array.prototype.isPrototype([]) //true

2、也可以从构造函数入手,利用对向的constructor属性
3、根据对象的class属性(类属性),跨原型链调用toString()方法。

Object.prototype.toString.call(Window);

4、Array.isArray()方法。

32、说说你对Promise的理解
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件监听——更合理和更强大。
Promise 有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。但是无法获取到pending状态,在promise中接受两个内置参数分别是resolve(成功)和reject(失败)
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。then方法可以传递两个回调函数第一个是成功,第二个是失败,失败回调也可以使用promisecatch方法回调,promise还有一个强大的功能那就是all方法可以组合多个promise实例,包装成一个新的 Promise 实例。

33、介绍一下async和await
async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而 await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。

async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案。目前async / await 在 IE edge中已经可以直接使用了,但是chrome和Node.js还没有支持。幸运的是,babel已经支持async的transform了,所以我们使用的时候引入babel就行。在开始之前我们需要引入以下的package,preset-stage-3里就有我们需要的async/await的编译文件。

34、箭头函数的作用域上下文和 普通函数作用域上下文 的区别
箭头函数其实只是一个密名函数的语法糖,区别在于普通函数作用域中的this有特定的指向,一般指向window,而箭头函数中的this只有一个指向那就是指当前函数所在的对象,其实现原理其实就是类似于之前编程的时候在函数外围定义that一样,用了箭头函数就不用定义that了直接使用this

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值