从一开始记住某个特性的某类特点到要去深挖原理,我不得不说............恩恩,都是面试官逼我的呀!他们会问为什么会出现事件冒泡和事件捕获两种?angularJS的理念是什么?new出来的对象和调用function有什么区别。。。

每次我下意识的反应都是:啊?

。。。。。。

然后在夜深人静的时候默默的看书看博客去还原他们问的问题的答案。

而且我想说知识点真的是太多太杂了。。。所以我会经常性的觉得我简直是弱爆了。。。。总是被活生生的摧残。。已不想多说一句话。。。

相关比较大块的东西,就总结在博客上

1、jQuery中怎么判断一个DOM树加载完毕?

这个问题之前是看到过的,但是没有深究,所以这次问到就答得乱七八糟。

平时用jQ会很顺手的上来写js就写$(function(){...}) [$(document).ready()]。但是它是有别于winodw.onload的,它们的触发时机是不同的

winodw.onload:是等到页面中所引用的img等所有的外部资源全部加载,并且在浏览器中显示后才执行!

                       所以,如果有很多很多的img或者是img很大会导致onload执行推迟

在JQ中,提供了domready,即$(function(){...}),它是在DOM树加载完毕后就立即执行,而不需要整个文档内容加载完成。

 

2、事件的过程是怎样的?(其实就是问事件捕获和事件冒泡啊!!)

简述事件冒泡和事件捕获的概念和发生的顺序:

 

 

(以点击事件为例)

冒泡:事件会从最内层的元素开始发生,一直向上传播,直到document对象

捕获:事件会从最外层开始发生,一直传播到被点击元素上

“DOM2级事件”规定事件流包括了三个部分:事件捕获阶段、处于目标阶段、事件冒泡阶段。事件流同时支持了事件捕获阶段和事件冒泡阶段

W3C规定,同时存在两种事件流时,首先进入捕获阶段,直到到达目标元素再进入冒泡阶段

addEventListener在IE8及以下的浏览器不兼容,可以使用attachEvent替代,attachEvent仅有两个参数,默认是冒泡模型。

以下图为例,详细解释这部分内容:

<div id="div1">div1
    <div id="div2">div2
        <div id="div3">div3
            <div id="div4">div4</div>
        </div>
    </div>
</div>
  1. 四个div全部设置为冒泡,点击div4——执行顺序:4-->3-->2-->1
  2. 四个div全部设置为捕获,点击div4——执行顺序:1-->2-->3-->4
  3. 1、3设置为冒泡,2、4设置为捕获,点击4——执行顺序:2-->4-->3-->1
  4. 下面我们给div2既添加冒泡又设置捕获:
        div1.addEventListener("click",function(){
            alert("div1");
        },false);
        div2.addEventListener("click",function(){
            alert("div2捕获");
        },true);
        div2.addEventListener("click",function(){
            alert("div2冒泡");
        },false);

    点击div2——执行顺序:div2捕获 --> div2冒泡 --> div1

        div1.addEventListener("click",function(){
            alert("div1");
        },false);
        div2.addEventListener("click",function(){
            alert("div2冒泡");
        },false);
        div2.addEventListener("click",function(){
            alert("div2捕获");
        },true);

    点击div2——执行顺序:div2冒泡 --> div2捕获 --> div1

     由上面两段代码和执行结果可得: 绑在点击元素身上的事件会按照代码的书写顺序执行!

  5. 还是分别执行上面两段代码,如果现在不是点击div2,而是点击div3或div4——执行顺序:div2捕获 --> div2冒泡 --> div1。这里就和书写顺序无关了,而是遵循W3C的规定,先执行捕获再执行冒泡!

关于阻止冒泡:

ev.stopPropagation() 等价于 ev.cancelBubble = true

前者符合W3C标准,不支持IE

后者不符合W3C

还有一个类似于ev.stopPropagation()的:ev.stopImmediatePropagation()

ev.stopPropagation():不会影响当前节点的任何事件监听器,会阻止事件流中当前节点后续的节点的事件

ev.stopImmediatePropagation():立即生效!当前节点也会被影响!

 

感觉面试官特别喜欢问这个问题!然后有的加点难度的,除了让你描述事件冒泡和事件捕获实现方式,

还会问:为什么会出现这两种过程?

这个问题。。。事件冒泡是微软提出的,事件捕获是网景提出的,两者没有优劣之分,都是为了解决事件流先后顺序的问题。但是相比较而言,事件冒泡的兼容性更好一些。

还会问:什么时候不需要阻止冒泡?什么时候要利用冒泡呢?

<div class="box">点我隐藏
    <div class="button">click点我变色</div>
</div>
<script>
    $('.box').click(function(ev){
        $('.box').hide();
    })

    $('.button').click(function(ev){
        ev.stopPropagation();     //  !!!
        $('.button').css('backgroundColor','blue')
    })
</script>

上面这个例子是这样的:如果点击.box希望整个.box隐藏,如果点击.box内部的.button则让.button变色。

此时,如果不加stopPropagation,那么点击.button后还是会隐藏整个.box。因为事件冒泡传递到.box上,触发了.box的点击事件。

所以,必须阻止冒泡才能实现上述想要的效果。

 

3、instanceof

    function Person(name){
        this.name = name;
    }
    var person1 = new Person('ning');
    var person2 = [];
    alert(person1 instanceof Person)    // true
    alert(person2 instanceof Person)    // false

形如:obj instanceof class    obj是class的一个实例的时候返回true,否则返回false。

instanceof通过返回一个布尔值来指出这个对象是否是这个特定类或者是它子类的一个实例!

在js中如何判断一个对象oStringObject是否为String?

js中String的初始化有两种方式:1、直接赋值,var str1 = 'abcd'

                                          2、String对象实例化,var str2  = new String('ac');

如果用第二种方式初始化,就不能用typeof来判断,因为此时typeof是判断基本数据类型的,null/[]/{}/对象/函数都属于object

这时可以用instanceof!

    var oStringObject = new String('aaa')
    alert(typeof oStringObject)   // object
    alert(oStringObject instanceof String)  // true
    alert(Object.prototype.toString.call(oStringObject)=='[object String]')   // true

后面两种方式都可以来判断oStringObject是不是String!

 

4、关于数组内置方法的返回值

 返回结果和注释都在代码中标明了!主要注意push/unshift的返回值是数组的长度!shift/pop的返回值是删掉的那个元素值!splice的返回值也是删掉的元素值!

    var str = 'abcdefg'
    //返回的就是截取的字符串
    console.log(str.substring(0,2))   // ab
    console.log(str.slice(0,2))   // ab

    // split返回的是一个数组
    console.log(str.split('b'))   // ['a','cdefg']
    console.log(str.split(''))    // ['a','b','c','d','e','f','g']

    var arr = ['aa','bb','cc']
    // join返回的是一个字符串
    console.log(arr.join())     //aa,bb,cc   (length=8)
    console.log(arr.join(''))   // aabbcc    (length=6)

    // push返回的是数组长度!!!push操作过后,arr就是push之后的新数组!!!
    console.log(arr.push(1))   // 4
    console.log(arr)           // ['aa','bb','cc',1]

    //unshift也是返回的是数组长度!!!
    console.log(arr.unshift('ning'))    // 5
    console.log(arr)                    // ['ning','aa','bb','cc',1]

    // pop返回的是删掉的那个元素,也就是arr最后一位的那个元素
    console.log(arr.pop())    // 1
    console.log(arr)          // ['ning','aa','bb','cc']

    // shift返回的是删掉的那个元素,也就是arr第一位的那个元素
    console.log(arr.shift())    // ning
    console.log(arr)          // ['aa','bb','cc']


    var arr2 = arr.splice(1,2,'new')
    console.log(arr)       // 返回splice操作之后的原来的数组
    console.log(arr2)      // 返回的是删掉的那个元素!! 效果与console.log(arr.splice(1,2,'new')) 等价

 

5、零碎

  • if判断内还有for循环内不允许写函数声明!!函数声明就不能写在运算中!但是if(function fn1(){...})会返回true,但是!!typepf fn1的结果是undefined
  • 下面这三个题~
    var str1 = 5 + 'nihao';
    var str2 = true + 'nihao';
    var str3 = 5 + true;
    console.log(typeof str1)  // string     '5nihao'
    console.log(typeof str2)  // string     'truenihao'
    console.log(typeof str3)  // number      5

关于null的一些容易混淆的:

    console.log(typeof null)  // object
    console.log(null instanceof Object)  //  false   null不是以Object为原型创建出来的!
    console.log(null == undefined)  // true
    console.log(false == undefined)  // false