一、apply、call
apply:应用某一对象的一个方法,用另一个对象替换当前对象。
call:调用一个对象的一个方法,以另一个对象替换当前对象。
共同之处:
都可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
不同之处:
1、apply:最多只能有两个参数——新this对象和一个数组 argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里面。如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj,并且无法被传递任何参数。
2、call:则是直接的参数列表,主要用在js对象各方法互相调用的时候,使当前this实例指针保持一致,或在特殊情况下需要改变this指针。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
apply和call功能一样,只是传入的参数列表形式不同,其中 thisArg 是你想指定的上下文,他可以是任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。
如果某个函数的参数数量是不固定的,当参数是明确知道数量时用 call ,而不确定的时候用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来遍历所有的参数。
二、bind
与上面不同的是,bind会返回一个改变this指向的新函数 ,注意这里强调的是新函数,其与之前的使用的不是同一块内存地址,所以当需要重复使用这个函数的时候,就不得不把其保存到一个变量,方便下次调用。上面的两个函数都是返回的执行结果,即调用即执行,此外,另外需要注意的地方是,bind函数中的首个参数,会自动成为返回新函数中参数的默认值,那么正式调用的时候,只需要给出除首个参数外,剩余参数即可。
当希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。
三、三者的联系:
apply 、 call 、bind 三者都是用来改变函数的this对象的指向的
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文
apply 、 call 、bind 三者都可以利用后续参数传参
bind是返回对应函数,便于稍后调用apply、call则是立即调用。
java中对象包含属性和方法, 方法即函数, 只有对象可以调用方法
但是js中一切皆对象, 函数是对象, 函数也可以调用方法
Function.prototype.call
Function.prototype.apply
Function.prototype.bind
Function.prototype.toString
为什么js语言会在function原型上挂上这四个函数?
因为好处太多了, 现在我就说一说call的应用
再深入思考一下, call语法是基于什么形成的呢 ?
了解底层语法有助于我们理解高级的语法
因为在底层的语法眼中, 高级语法只不过是工具, 根本不算语法, 不过是由我定义构建处理来的
理解call函数, 核心必要知识
哈哈哈, v8内部的不知道, 反正js基于现有语法就有这个能力 (还有解法, 基于 proto ,原型链的方式, var temp = Object.create(null)), 利用干净的地方, 防止覆盖原对象的函数
显然, 我们自己的上面的mycall还要很多问题
这里我们就实现了自己的call, 以后看见call就知道都不过是些雕虫小技了(当然真实的实现方式肯定需要考虑更多因素和性能, 而且在v8更大的环境下, 可能还不止一种实现方式,保持谦虚)
代码如下:<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-type" content="text/htmlcharset=utf-8">
<title>远程网页源代码读取</title>
<style type="text/css">
/* 页面字体样式 */
body, td, input, textarea {
font-family:Arial
font-size:12px
}
</style>
<script type="text/javascript">
//用于创建XMLHttpRequest对象
function createXmlHttp() {
//根据window.XMLHttpRequest对象是否存在使用不同的创建方式
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest()//FireFox、Opera等浏览器支持的创建方式
} else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")//IE浏览器支持的创建方式
}
}
//直接通过XMLHttpRequest对象获取远程网页源代码
function getSource() {
var url = document.getElementById("url").value//获取目标地址信息
//地址为空时提示用户输入
if (url == "") {
alert("请输入网页地址 。")
return
}
document.getElementById("source").value = "正在加载……"//提示正在加载
createXmlHttp()//创建XMLHttpRequest对象
xmlHttp.onreadystatechange = writeSource//设置回调函数
xmlHttp.open("GET", url, true)
xmlHttp.send(null)
}
//将远程网页源代码写入页面文字区域
function writeSource() {
if (xmlHttp.readyState == 4) {
document.getElementById("source").value = xmlHttp.responseText
}
}
</script>
</head>
<body>
<h1>远程网页源代码读取</h1>
<div>
地址:<input type="text" id="url">
<input type="button" onclick="getSource()" value="获取源码">
</div>
<textarea rows="10" cols="80" id="source"></textarea>
</body>
</html>