冒泡

当子元素上面所有的父元素注册有相同的事件时,你执行每个元素的事件时,会发生什么呢?这就是js中的事件流,即事件发生的顺序。这里用click来举例

背景

在以前,浏览器的兼容性比现在要小得多,在浏览器发展到第四代的时候,Netscape(网景)提出事件捕获,而Internet Explorer提出事件冒泡。在W3C组织的统一下,JS支持了冒泡流和捕获流,最终被应用在现在浏览器里。
注:但是目前低版本的IE浏览器还是只能支持冒泡流(IE6,IE7,IE8均只支持冒泡流),所以为了能够兼容更多的浏览器,建议大家使用冒泡流

三个阶段
在DOM兼容浏览器中,事件流分为3个阶段:
(1)捕获阶段:事件从Document节点自上而下向目标节点传播的阶段;
(2)目标阶段:真正的目标节点正在处理事件的阶段;
(3)冒泡阶段:事件从目标节点自上而下向Document节点传播的阶段。

例:

<style>
    #box1 {
        width: 300px;
        height: 300px;
        background-color: red;
    }
    #box2 {
        width: 200px;
        height: 200px;
        background-color: green;
    }
    #box3 {
        width: 100px;
        height: 100px;
        background-color: blue;
    }
</style>

<div id="box1">box1
    <div id="box2">box2
        <div id="box3">box3
        </div>
    </div>
</div>
  • 当js代码如下时
<script>
        function $(el) {
            return document.getElementById(el);
        }
        $('box1').onclick = function() {
            console.log('box11');
        };
        $('box2').onclick = function() {
            console.log('box22');
        };
        $('box3').onclick = function() {
            console.log('box33');
        };
        window.body.onclick = function() {
            console.log('body00');
        }
        //onclick 只支持事件冒泡
        window.body.addEventListener('click', function() {
            console.log(this.id);
        }, true);
    </script>
  1. 事件捕获阶段:当addEventListener第三个参数为true时
    点击box3,输出 body box33 box22 box11 body00
    点击box2,输出 body box22 box11 body00
    点击box1,输出 body box11 body00
  2. 事件冒泡阶段:当addEventListener第三个参数为false时
    点击box3,输出 box33 box22 box11 body00 body
    点击box2,输出 box22 box11 body00 body
    点击box1,输出 box11 body00 body
  3. 当js代码改为如下时
<script>
        function $(el) {
            return document.getElementById(el);
        }
        $('box1').addEventListener('click',function () {
          console.log('box11');
        }, true)
        $('box2').addEventListener('click',function () {
          console.log('box22');
        }, true)
        $('box3').addEventListener('click',function () {
          console.log('box33');
        }, true)
        window.body.addEventListener('click', function() {
            console.log('body');
        }, true);
    </script>
  1. 事件捕获阶段:当addEventListener第三个参数为true时
    点击box3,输出 body box22 box11 box33
    点击box2,输出 body box11 box22
    点击box1,输出 body box11
  2. 事件冒泡阶段:当addEventListener第三个参数为false时
    点击box3,输出 box33 box22 box11 body
    点击box2,输出 box22 box11 body
    点击box1,输出 box11 body

事件委托
如果在li上绑定click事件,那么新添加的li元素不会有这个click事件。此时应该在ul上绑定事件,根据事件捕获的原理,事件会自上而下传递给li。通过event.target找到这个li元素

阻止事件冒泡
在w3c模型中你必须调用事件的stopPropagation()方法
stopPropagation()
在微软的模型中,你必须设置事件的cancelBubble的属性为true
window.event.cancelBubble = “true
无法在捕获阶段阻止事件冒泡

call、applay、bind的区别

在不同场景中this的指向不同,但有些情况我们为了使用某种特定环境的this引用,这是后就需要改变this的指向

例如:在使用定时器时,在外部备份this引用,然后在定时器内部引用
call()
语法
fun.call(thisArg, arg1, arg2,……)
thisArg在fun运行时指定的this值在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
arg1, arg2,……指定的参数列表
返回值
返回值是你调用的方法的返回值,若该方法没有返回值,则返回undefined
使用call方法调用父构造函数

function Product(name, price) {
    this.name = name;
    this.price = price;
  }
  function Food(name, price) {
    Product.call(this, name, price);
    this.category = 'food';
  }
  console.log(new Food('zs', 23));//{name:zs,price:23,category:food}

使用call方法调用匿名函数

var animals = [{
        species: 'Lion',
        name: 'King'
      },
      {
        species: 'Whale',
        name: 'Fail'
      }
    ];
    for (var i = 0; i < animals.length; i++) {
      (function (i) {
        this.print = function () {
          console.log(i + ' ' + this.species + ': ' + this.name);
        }
        this.print();
      }).call(animals[i], i);
    }//0 Lion King \n 1 Whale  Fail

使用call方法调用函数并且指定上下文的’this’

function greet() {
  var reply = [this.person, 'is', this.role].join(' ');
  console.log(reply);
}
var i = {
  person: 'zs', role: 'person'
};
greet.call(i);//zs is person

bind

语法

fun.bind(thisArg, [arg1, arg2,……])

当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效。

当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

都是将this指向了thisArg;

var num = {
    x: 10,
    add: function(){
        return this.x;
    }
}
var getx = num.add;
var bindX = getx.bind(num);
console.log(bindX());//bind()返回一个新的函数
var callX = getx.call(num);
console.log(callX)//call直接调用函数
var applyx = getx.apply(num);
 console.log(applyx)//apply直接调用函数
//apply只有两个参数,第二个参数是数组
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值