JavaScript进阶【四】JavaScript中的this,apply,call的深入剖析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--this的使用-->
<!--(1)this的指向
作为对象的方法调用
作为普通函数调用
构造器调用
Function.prototype.call或Function.prototype.apply调用
-->
<!--1)this作为对象的方法调用
当函数作为对象的方法被调用时,this指向该对象:
-->
<script>
var obj = {
a: 1,
getA: function () {
alert(this == obj); // true
alert(this.a); //1
}
}
obj.getA(); // 2. 作为普通函数调用使用
window.name = "gloabalName";
var getName = function () {
// 这哭的this指向的是window对象
return this.name;
} var myObject = {
name: "xiuxiu",
getNameA: function () {
// 这里的this指向的是myObject 对象
alert(this); // window
return this.name;
}
} console.log(getName()); var a = myObject.getNameA; //globalName
//console.log(a); // xiuxiu
console.log(a()); var innerText = "我是全局变量的innerText";
// callback方法的使用
var button = document.createElement("button");
button.innerText = "打开";
button.id = "btn";
document.body.appendChild(button);
button.onclick = function (ev) { // 定义一个that , 让这个that指向button对象
var that = this; // alert(this); button
// 这里的this指向的是触发这个事件的那个对象
console.log(this.innerText); var callback = function () {
// 这里的this指向的是window对象
// 注意:在ES5的strict模式下,this已经被规定不会指向全局对象,而是undefined
console.log(this.innerText); //undifined // 这里的that 指向的是这个按钮对象, 不是window对象
console.log(that.innerText);
}
callback();
} //3. 构造器调用
// 构造器里的this就指向返回的这个对象
var myClass = function (name, sex) {
this.name = name;
this.sex = sex; alert(this.name + " " + this.sex);
};
var male = new myClass("xiaohong", "male"); var myClass = function (name) {
//console.log(this.name); //undifined
this.name = name; console.log(this.name + " " + name); // 只有返回出去之后,这个name属性就会被外界修改
return {
name: "hahaha"
}
}
var cls = new myClass("xiuxiu");
alert(cls.name); // 4)Function.prototype.call和Function.prototype.apply调用
// 跟普通的函数调用相比,用Function.prototype.call或Function.prototype.apply可以动态的改变传入函数的this
var obj1 = {
name: "xiuxiu",
getName: function () {
return this.name;
}
}
var obj2 = {
name: "Jack"
}
console.log(obj1.name); // xiuxiu
console.log(obj1.getName.call(obj2)); // jack var obj3 = {
myname: "seven",
getName: function () {
return this.myname;
}
}
// 此时在调用this指向 obj3对象
console.log(obj3.getName()); // seven // 修改this的指向
// 这里是通过getname2这个普通函数区调用的, 此时this 指向的是window对象
// 但是全局中没有getname2这个方法
var getname2 = obj3.getName;
alert(getname2()); //undifined // document.getElementById的使用错误
var getId = function (id) {
//alert(this); // 这里的this指向的widnow
return document.getElementById(id);
}
var id = getId("btn");
console.log("id:" + id); // ButtonElement // 这里把这个函数的this修改为指向document对象
//var getId = document.getElementById;
//id = getId("btn");
//console.log("id:"+id); // this的使用理解.html?_ijt=7mjupf008evikdgvnqbeddk23d:146 Uncaught TypeError: Illegal invocation // 手动修改this 的指向
document.getElementById = (function (func) {
return function () {
// 这里强制让func对象指向documen对象
return func.apply(document, arguments);
}
})(document.getElementById); var getId = document.getElementById;
var button = getId("btn");
console.log(button); // <button id="btn">打开</button>
console.log(button.id); // 二、call和apply的使用
var func = function (a, b, c) { "use strict";
// 显示一下这个函数体内的this指向是个啥
alert(this);
console.log([a, b, c]);
}
// ƒ (a, b, c) {
/*console.log([a, b, c]);
}*/
console.log(func);
// func()表示直接去调用这个函数
console.log(func()); // undifined // 通过apply方法可以去修改这个函数体内的 this 的指向,可以任意修改, window, document
// 第一个参数也是代表函数体内的this指向,从第二个参数开始往后,每个参数被依次传入函数
func.apply(null, [1, 2, 3]); // this指向window
// 在严格模式"use strict"下上面的this指向为null, 不使用严格模式会指向window
func.apply(null, [1]); // this指向window //如果我们传入的第一个参数为null,函数体内的this会指向默认的宿主对象。在浏览器中则是window
func.apply(null, [0, 1]); // this指向window
//console.log(func());
func.apply(document, [0, 1, 2]); // this指向document
func.apply(this, [0, 1]); // this指向window // 利用函数求出最大值
console.log(Math.max.apply(null, [1, 2, 3]));
console.log(Math.max(1, 2, 3)); // 三、call和apply在实际开发中的用途
// 1.)修改 this的指向
var obj1 = {
//alert(this);
name: "seven"
}
var obj2 = {
//alert(this);
name: "haha" } window.name = "window";
var getName = function () {
console.log(this.name);
}
// 全局调用函数
getName(); // this指向的是window
getName.call(obj1); // this指向的是obj1对象
getName.call(obj2); // this指向的是obj2对象 // 添加一个事件
document.addEventListener("click", function (ev) {
// 这里的this 指向的是触发这个事件的那个对象
console.log(this); // document function Add(a, b) {
console.log(this);
} // 这个相当于是全局调用,thisz指向的是window对象
Add(10, 1); // window
// 修正这个this 的指向
// 这里的this指向的还是触发这个事件的那个对象
Add.call(this); // document
}); // 2).Function.prototype.bind
// Function.prototype.bind,用来指定函数内部的this指向
Function.prototypebind = function (context) {
var self = this; return function () {
console.log(context+"is"+ this); // 修改this(self)的指向为context对象
return self.apply(context, arguments);
}
} var obj = {
name: "xiuxiuDesign"
}
var getName = function () {
// 修改this的指向为obj对象
console.log(this.name);
}.bind(obj);
getName(); // 3).借用其它对象的方法
var A = function (name) {
this.name = name;
}
var B = function () {
// 修改A这个的this对象指向B
A.apply(this, arguments); // Arguments ["xiuxiu is a good man", callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log(arguments);
} B.prototype.getName = function () {
//
return this.name;
}
var b = new B("xiuxiu is a good man");
console.log(b.getName()); // 想往argumments中添加一个新的元素,通常会借用Array.prototype.push
(function () {
Array.prototype.push.call(arguments, 3);
console.log(arguments);
})(1, 2, 1, 3) // 想把arguments转成真正的数组的时候,可以借用Array.prototype.slice方法,想截取arguments列表中的头一个元素时,可以使用Array.prototype.shift方法,这种机制的内部原理,我们可以翻开V8引擎源码,以Array.prototype.push方法为例
var a = {};
// 修改Array这个数组的指向, 让这个数组的push的this指向a的引用, 也就是a这个对象
Array.prototype.push.call(a, 'first');
Array.prototype.push.call(a, 'second'); // 通过调用Array的push 方法, 同时修改了this 的指向为a这个对象的引用
console.log(a.length);
console.log(a[0]); // JavaScript的一种继承方式
var AA = function (name, age) {
this.name = name;
this.age = age;
}
AA.prototype = {
getName : function () {
alert(this.name);
}
} var BB = function () {
}
// 让BB对象继承于AA对象
BB.prototype = new AA("AAA", 19); var aa = new AA("xiuxiu", 18);
console.log(aa.name +" "+aa.age); // xiuxiu, 18
var bb = new BB();
console.log(bb.name+" "+bb.age); // AAA 19 </script> </body>
</html>
JavaScript进阶【四】JavaScript中的this,apply,call的深入剖析的更多相关文章
- JavaScript进阶(五)js中取小数整数部分函数
js中取小数整数部分函数 丢弃小数部分,保留整数部分 js:parseInt(7/2) 向上取整,有小数就整数部分加1 js: Math.ceil(7/2) 四舍五入 js: Math.round(7 ...
- JavaScript进阶(四)js字符串转换成数字的三种方法
js字符串转换成数字的三种方法 在js读取文本框或者其它表单数据的时候获得的值是字符串类型的,例如两个文本框a和b,如果获得a的value值为11,b的value值为9 ,那么a.value要小于b. ...
- 二、JavaScript语言--JS基础--JavaScript进阶篇--JavaScript内置对象
1.什么事对象 JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的,如:字符串的长度.图像的长宽等: 对象的方 ...
- Javascript进阶篇——( JavaScript内置对象---上-Date,string,charAt,indexOf,split,substring,substr)笔记整理
什么是对象JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法.对象的属性:反映该对象某些特定的性质的,如:字符串的长度.图像的长宽等:对象的方法:能够在 ...
- Javascript进阶篇——( JavaScript内置对象---下)--Array数组对象---笔记整理
Array 数组对象数组对象是一个对象的集合,里边的对象可以是不同类型的.数组的每一个成员对象都有一个“下标”,用来表示它在数组中的位置,是从零开始的数组定义的方法: 1. 定义了一个空数组: var ...
- Javascript进阶篇——( JavaScript内置对象---下)--Math对象---笔记整理
Math对象使用 Math 的属性和方法: <script type="text/javascript"> var mypi=Math.PI; var myabs=Ma ...
- mysql进阶(四)mysql中select
mysql中select * for update 注: FOR UPDATE 仅适用于InnoDB,且必须在事务区块(BEGIN/COMMIT)中才能生效. 作用 锁定该语句所选择到的对象.防止在 ...
- 面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗
一.前言 不知道大家还记不记得前几篇的文章:<面试官:能解释一下javascript中的this吗> 那今天这篇文章虽然是介绍javascript中bind.apply和call函数 ...
- JavaScript进阶系列02,函数作为参数以及在数组中的应用
有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var su ...
随机推荐
- 解决ubuntu下wordpress设置固定链接后文章无法打开
1.首先查看是否开启了Apache的rewrite功能,新建一个phpinfo的php文档 <?php phpinfo(); ?> 保存为info.php文件 放在www目录下并用浏览器打 ...
- 洛谷——P1060 开心的金明
https://www.luogu.org/problem/show?pid=1060#sub 题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的 ...
- rabbitmq安装、集群搭建
rabbitmq的安装: CentOS上面部署: 首先修改hosts文件 修改hosts文件vi /etc/hosts1.1.1.1 hostname 2.2.2.2 hostname 3.3.3.3 ...
- Apache vs. Nginx
精简版 Apache:出名比较早,09年左右是最流行的时期,功能强大,可以根据需求配置为基于进程,基于线程或者基于事件的,但是消耗内存较多,对硬件需求较高,内存是影响服务器性能的最关键因素,在VPS上 ...
- uva 10276 / pc 110908
黑书上说用二分图的知识来解,但我想不出来,只好找规律 发现,一条柱时为1,两条柱时为4.三条柱时为8.. 这些1,3,7,11的数字加1后,都是下一条柱的最底部的数字,而且一条柱的数字之和总是按照这样 ...
- 125条常见的java面试、笔试题大汇总
1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解所有问题,而仅仅是选择当中的一部分,临时不用部分细节.抽象包含两个方面,一是过程抽象. ...
- Ralink5350开发环境搭建
一.安装虚拟机(Oracle VM VirtualBox 或 VMware Workstation) 二.在虚拟机中安装linux操作系统(当前使用的是Ubuntu1204桌面版) 三.配置linu ...
- 《Head First 设计模式》学习笔记——复合模式
模型-视图-控制器(MVC模式)是一种很经典的软件架构模式.在UI框架和UI设计思路中扮演着很重要的角色.从设计模式的角度来看,MVC模式是一种复合模式.它将多个设计模式在一种解决方式中结合起来,用来 ...
- luogu2429 制杖题
题目大意 求不大于 m 的. 质因数集与给定有n个元素的质数集有交集的自然数之和. 数据范围 1 2 3 n*m<=10^7 4 5 n<=2,m<=10^9 6 7 n<=2 ...
- sql server 2012中red gate的sql source control消失
找到C:\ProgramData\Microsoft\SQL Server Management Studio\11.0\Addins路径,用notepad++打开RedGate.SIPFramewo ...