Function.call Function.apply
将其他对象的方法"借用"在自己身上用(this) Function.call 和Function.apply的行为非常相似 只不过是Function.call接受的参数列表 Function.apply接受的是参数数组
var friend = { food:0, eat:function(amount,money) { this.food = amount; console.log(money); } }//friend对象有一个eat方法 设置自己的food属性 并且输出相应的money var me = { food:0, isHungry:function() { return this.food < 100; } } //me只有一个根据food值判断是否饥饿的方法 me很懒 想使用朋友的eat方法(可以理解为喂我吃) 通过this的绑定eat方法中的this指向了我 所以我不在饥饿了 console.log(me.isHungry()); friend.eat.call(me,100,"120"); //call 接受参数列表 console.log(me.isHungry()); friend.eat.apply(me,[100,"120"]); //apply 接受参数数组 console.log(me.isHungry());
生成对象的三种方法
对象字面量
var dog = { name:"ha", say:function() { return "wang"; } }
dog.age = 9;
console.log(dog.age) //9
其实可以理解为对象字面量是Object.create()的一种快捷调用
var dog = Object.create(Object.prototype,{ name:{ value:"sss" }, say:{ value:function() { return "wang"; } } }); console.log(dog.say()); //wang //会在下面介绍Object.create()
这种方式是创建简单的一次性对象的最佳选择
new Object()
var dog = new Object({ name:"haha", say:function() { return "wang"; } }); console.log(dog.say());//wang
通过原生对象的构造函数进行对象的创建 注意原生对象的构造函数是属于全局命名空间的 也就是通过winow.Object能获取到这个构造函数(有可能被修改了)
Object.create(args1,args2) 第一个参数是提供原型的对象 第二个参数是提供可选属性的对象 Object.create() 提供了new操作符的优点
var person = { getOld:function() { this.age = this.age + 10; return this.age; } } var haha = Object.create(person,{ age:{ value:10, writable:true } }); console.log(haha.getOld()); //20
第二个参数可选属性对象相应的属性配置需要配置 否则 默认为false 就是不可修改 不可以枚举
window.getComputedStyle(元素,伪类) 第二个参数不是必须的 使用这个方法可以获得当前元素所有使用的最终的CSS属性值 返回一个样式声明对象 它是一个只读的对象
对比 element.style element.style 也能获得一个元素的样式声明对象 但是element.style只能获取元素style属相里面设置的css属性 但是element.style 是可以读写的
在老版本的IE上是不支持window.getComputedStyle()这个方法的 可以使用element.currentStyle 它同样是一个只读的对象 我在IE11 上window.getComputedStye() element.currentStyle 都支持
2016 3 13 发现在chrome中并不支持element.currentStyle 也就是这玩意还是个IE搞特殊化的东西
要获取我们获得的样式声明对象obj(无论是通过window.getComputedStyle() 或者 element.currentStyle获取的) 可以通过 obj.attrName 或者 obj['attrName'] 这样的方式获取
但是在不同的浏览器下同样的属性 attrName 的定义又有可能不同 通用的方法是 使用getPropertyValue('attrName') (不支持驼峰 获取background-color getPropertyValue('background-color'))
element.getBoundingClientRect() 返回一个对象 里面包含六个属性 元素的width height 元素的上下左右相对于浏览器窗口的距离 仔细理解上下左右相对于浏览器窗口的位置
我们可以通过这个方法获取元素的当前的位置 通过以下这样的方式
var interval = setInterval(function(){ var rectObj = b.getBoundingClientRect(); var x = rectObj.left + document.documentElement.scrollLeft; var y = rectObj.top + document.documentElement.scrollTop; // 当前元素距离窗口的位置 + 当前滚动条的位置 console.log('当前x坐标' + x + ' 当前的y坐标 ' + y); },3000); //这样拖动滚动条也能得到正确的元素的位置
2016 3 13 这里的top left bottom right 是没有单位的
element.getClientRects() 该方法返回一个TextRectangle集合 也就是TextRectangleList对象 每一个TextRectangle包含 top right bottom left width height 6个属性 TextRectangl是针对文本区域的一个描述 也就是该方法只能在inline的文本元素上使用 (这里的top right bottom left 也是相对于浏览器窗口的位置)
<div id="test"> <span id="b">sdadasda dadasd sadadad </span> </div>
对于上面的页面结构 在页面上是这样显示的(由于空格的作用 和 外层div 的限制 文本形成了 3行 )
形成了3个文本区域 也就是3个TextRectangle对象 这三个TextRectangle对象形成了一个TextRectangleList集合
var span = document.getElementById('b'); var list = span.getClientRects(); var length = list.length; console.log(length);//3
通过length我们就可以判断文字是否换行 并且换了几行 在结合鼠标的位置 就可以判断鼠标停留在哪行了
var span = document.getElementById('b'); var list = span.getClientRects(); var length = list.length; console.log(length); span.onclick = function(event) { var i; var mouseY = event.clientY; var mouseX = event.clientX; for(i = 0;i < length;i++) { if( mouseY >= list[i].top && mouseY <= list[i].bottom && mouseX >= list[i].left && mouseX < list[i].right) { console.log(i); } } } // 上面的例子就可以通过判断测试出鼠标点击的是哪行
element.addEventListener(event,handler,useCapture)
event 必须 需要监听的时间 例如 click
handler 必须 监听时间发生后的处理函数
useCapture 可选 布尔值 指定事件是在捕获或者冒泡阶段执行 true 捕获阶段执行 false 冒泡阶段执行 默认false
我们可以为一个事件添加多个处理程序
var btn = document.getElementById('btn'); function a() { console.log('a'); } function b() { console.log('b'); } btn.addEventListener('click',a); btn.addEventListener('click',b);
上面的例子中我们为click事件添加了两个事件处理程序 当点击页面中的btn的时候 两个事件监听程序都进行了处理 并且是按照绑定的先后顺序进行事件的处理的
element.removeEventListener(event,hadler) 例如上面的例子 我们可以通过下面的语句移除事件监听程序
btn.removeEventListener('click',a);
**通过匿名函数绑定的事件无法移除** (因为我们再次传入的handler并不是同一个函数)
有时候我们不想定义函数的声明 也就是想要通过匿名函数的方式去绑定事件处理程序
var btn = document.getElementById('btn'); var handler = function () { console.log(1); } btn.addEventListener('click',handler); btn.removeEventListener('click',handler); //也就是两个handler要指向同一个函数
关于添加事件监听的跨浏览实现 请参考我的另一篇blog js事件小记
下面这种情况也许不大常见 我们想移除上面绑定的事件处理程序怎么操作呢
var btn = document.getElementById('btn'); function a() { console.log(1); } function b() { console.log(2); } btn.addEventListener('click',a); btn.addEventListener('click',b); btn.addEventListener('click',function test() { console.log(3);//加断点 })
在这个例子我们在click事件上绑定了有函数声明的函数 和 有名的匿名函数 (我的理解是外界无法取到它的引用 而且我们使用匿名函数的时候 也最好给它一个名字 这样在控制台调试的时候通过堆栈的调用能查看我们调用的函数) 上面的例子中我在标注出加了断点
可以看出它调用了test函数 回归正题 对于这种情况 我们要移除绑定的事件监听程序呢(里面还有一个万恶的匿名函数) 首先是可以通过一个一个的removeEventListener()来进行的(对于匿名函数没有办法) 我们可以通过cloneNode()的方法 对要移除事件的元素进行复制 在复制的时候不会保留上面绑定的事件监听程序 并且匿名函数也移除了 下面是简单的实现
var new_btn = btn.cloneNode(true); btn.parentNode.replaceChild(new_btn,btn); //通过这种方式上面绑定的事件监听程序都移除了