面试汇总javascript

获取元素相对于父元素的位移

js: offsetLeft左位移 offsetTop上位移
jquery: position().left; position().top

js删除数组中空元素

function removeEmptyArrayEle(arr){    
  for(var i = 0; i < arr.length; i++) {
   if(arr[i] == undefined) {
      arr.splice(i,1);
      i = i - 1; // i - 1 ,因为空元素在数组下标 2 位置,删除空之后,后面的元素要向前补位,
                       // 这样才能真正去掉空元素,觉得这句可以删掉的连续为空试试,然后思考其中逻辑
    }
   }
   return arr;
};

javascript 的typeof 都返回哪些数据类型

number, boolean, string, undefined, object, function.

如何判断一个对象的数据类型为数组

使用Array.isArray(arr)和Oblect.prototype.toString.call(arr)是比较好的方法

使用多种方法截取字符串“www.bestmath.cn”中的math

  • 函数:substring()
    定义:substring(start,end)表示从start到end之间的字符串,包括start位置的字符但是不包括end位置的字符。
    功能:字符串截取,比如想从"MinidxSearchEngine"中得到"Minidx"就要用到substring(0,6)
  • 函数:substr()
    定义:substr(start,length)表示从start位置开始,截取length长度的字符串。

如何理解 JavaScript 的原型?

  • 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(null除外)
  • 所有的函数,都有一个prototype属性,属性值也是一个普通的对象
  • 所有的引用类型(数组、对象、函数),都有一个proto属性,属性值是一个普通的对象
  • 所有的引用类型(数组、对象、函数),proto属性值指向它的构造函数的prototype属性值

原型示例

function Foo(name, age) {  //构造函数
this.name = name
}
Foo.prototype.alertName = function () {
  alert(this.name)
}
// 创建示例
var f = new Foo('zhangsan')
f.printName = function () {
    console.log(this.name)
}
// 测试
f.printName()
f.alertName()...

执行printName时很好理解,但是执行alertName时发生了什么?这里再记住一个重点 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找,因此f.alertName就会找到Foo.prototype.alertName

那么如何判断这个属性是不是对象本身的属性呢?使用hasOwnProperty,常用的地方是遍历一个对象的时候

var item
for (item in f) {
// 高级浏览器已经在 for in 中屏蔽了来自原型的属性,但是这里建议大家还是加上这个判断,保证程序的健壮性
if (f.hasOwnProperty(item)) {
      console.log(item)
   }
}...

传送门

闭包概念?

  • javascript不存在块级作用域,但是有函数作用域:函数内定义的的所有变量在函数外是不可见的。
  • 内部函数可以访问的变量即来自他自身的作用域,也可以来自其“父级”作用域,这就形成了一条作用域链。
  • 利用闭包突破作用域链:将内部函数升级为全局变量或者通过外部函数传递(或返回)给全局空间即可。
  • 所以说:如果一个函数会在其父级函数返回之后留住父级作用域的链接的话,相关闭包就会被创造出来。
unction F1() {
    var a = 100
    return function () {
        console.log(a)
    }
}
var f1 = F1()
var a = 200
f1()

自由变量将从作用域链中去寻找,但是 依据的是函数定义时的作用域链,而不是函数执行时,以上这个例子就是闭包。闭包主要有两个应用场景:

  • 函数作为返回值,上面的例子就是

  • 函数作为参数传递,看以下例子

    function F1() {
      var a = 100
      return function () {
          console.log(a)
      }
    }
    function F2(f1) {
      var a = 200
      console.log(f1())
    }
    var f1 = F1()
    F2(f1)
    

以上结果是100 undefined 原因是f1()没有返回值,所用console.log(f1())undefined

说一下异步和单线程?

JS 需要异步的根本原因是 JS 是单线程运行的,即在同一时间只能做一件事,不能“一心二用”。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
参考

  • 前端异步的场景
    定时 setTimeout setInterval
    网络请求,如Ajax 加载

如何使用事件代理?有何好处?

利用冒泡的原理,把事件加到父级上,当子元素的事件冒泡到父ul元素时,你可以检查事件对象的target属性,捕获真正被点击的节点元素的引用。

var div1 = document.getElementById('div1')
div1.addEventListener('click', function (e) {
 // e.target 可以监听到触发点击事件的元素是哪一个
   var target = e.target
   if (e.nodeName === 'A') {
     // 点击的是 元素
     alert(target.innerHTML)
   } 
})
  • 使用事件代理的好处
    使代码简洁
    减少浏览器的内存占用
    通过事件委托,新添加的元素自动绑定事件
    参考

property 和 attribute 的区别是什么?

property

DOM 节点就是一个 JS 对象,它符合之前讲述的对象的特征 —— 可扩展属性,因为 DOM 节点本质上也是一个 JS 对象。因此,如下代码所示,p可以有style属性,有className nodeName nodeType属性。注意,这些都是 JS 范畴的属性,符合 JS 语法标准的。

var pList = document.querySelectorAll('p')
var p = pList[0]
console.log(p.style.width)  // 获取样式
p.style.width = '100px'  // 修改样式
console.log(p.className)  // 获取 class
p.className = 'p1'  // 修改 class

// 获取 nodeName 和 nodeType
console.log(p.nodeName)
console.log(p.nodeType)
attribute

property 的获取和修改,是直接改变 JS 对象,而 attribute 是直接改变 HTML 的属性,两种有很大的区别。attribute 就是对 HTML 属性的 get 和 set,和 DOM 节点的 JS 范畴的 property 没有关系。

var pList = document.querySelectorAll('p')
var p = pList[0]
p.getAttribute('data-name')
p.setAttribute('data-name', 'juejin')
p.getAttribute('style')
p.setAttribute('style', 'font-size:30px;')...

什么是同源策略?跨域的方法?

浏览器中有 同源策略 ,即一个域下的页面中,无法通过 Ajax 获取到其他域的接口。例如有一个接口http://m.juejin.com/course/ajaxcourserecom?cid=459,你自己的一个页面http://www.yourname.com/page1.html中的 Ajax 无法获取这个接口。这正是命中了“同源策略”。如果浏览器哪些地方忽略了同源策略,那就是浏览器的安全漏洞,需要紧急修复。
但是 HTML 中几个标签能逃避过同源策略——

你可能感兴趣的:(面试汇总javascript)