getBoundingClientRect的兼容函数分析(arguments.callee的妙用)

getBoundingClientRect的兼容函数分析


    function getBoundingClientRect(element) {
        if (typeof arguments.callee.offset != "number") {
            var scrollTop = document.documentElement.scrollTop
            var temp = document.createElement("div")
            temp.style.cssText = "position:absolute;left:0;top:0"
            document.body.appendChild(temp)
            arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;
            document.body.removeChild(temp)
            temp = null
        }
        var rect = element.getBoundingClientRect()
        var offset = arguments.callee.offset
        //offset在IE7中是-2 其他是0
        return {
            left: rect.left + offset,
            right: rect.right + offset,
            top: rect.top + offset,
            bottom: rect.bottom + offset
        }
    }
  • DOM元素通过原型链中的Element构造函数获得方法getBoundingClientRect()
  • 而在IE7及更早的版本中位于左上角(0,0)处的元素的位置会返回(2,2)的坐标,所以才需要重新写一个函数。

在一些书里写是IE8及更早的版本,然而经测试是IE7及更早的版本才会返回(2,2)。

  • 重点!!!这里的if语句非常漂亮

  • 因为对于浏览器左上角的测试只需要一次即可!!!所以这里对arguments.callee进行赋值。
    第一次调用函数时arguments.callee不存在offset属性,所以进入if中的语句块,对arguments.callee.offset进行赋值。
    因为对arguments.callee赋值是直接对函数本身进行修改。(也就是说接下来每一次调用这个函数时,函数都将自带arguments.callee.offset)
    如图,调用过一次之后再console.dir()的结果是

  • 在调用前是这样的

  • 我认为此函数应该如下更改更容易理解

    function MygetBoundingClientRect(element) {
        //判断是否已经运行过此函数,如果已运行过,则会在arguments.callee.offset保存浏览器的数据,也就不再进入if语句块
        if (typeof arguments.callee.offset != "number") {

            //计算滚动条外的长度(用于去除)
            var scrollTop = document.documentElement.scrollTop

            //创建一个dom元素用于测量左上角的坐标是(0,0)还是(2,2)
            var temp = document.createElement("div")

            //这一步非常重要,必须绝对定位定位在左上角,不然会加到文档的末尾测量出现巨大偏差。
            temp.style.cssText = "position:absolute;left:0;top:0"


            document.body.appendChild(temp)

            //去除窗口外的距离,如果IE<=7则
            arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;

            //移除元素
            document.body.removeChild(temp)
            //解除对DOM对象的引用,减少其引用数,确保正常回收其占用的内用
            temp = null
        }

        //这里的getBoundingClientRect方法是继承于Element的原型方法的,而不是我们定义的函数,所以我区分了一下
        var rect = element.getBoundingClientRect()
        var offset = arguments.callee.offset

        console.log(offset)


        return {
            left: rect.left + offset,
            right: rect.right + offset,
            top: rect.top + offset,
            bottom: rect.bottom + offset
        }
    }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值