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 ...
随机推荐
- [bzoj3530][Sdoi2014]数数_AC自动机_数位dp
数数 bzoj-3530 Sdoi-2014 题目大意:给你一个整数集合,求所有不超过n的正整数,是的它的十进制表示下不能再一段等于集合中的任意数. 注释:$1\le n \le 1200$,$1\l ...
- G - Balanced Lineup
G - Balanced Lineup POJ - 3264 思路:水题,线段树的基本操作即可. #include<cstdio> #include<cstring> #inc ...
- JQuery学习(5-AJAX1)
<? php /* * 保护AJAX请求的方式 */ /* * 1. 防止表单的自己主动提交 * 对表单的submit提交进行控制. 设置一个全局变量submitError,在进行验证的方法体中 ...
- HTML【2】表单提交与服务层的模拟(具体解释get与post提交方式的不同)
在HTML[1]中已经说明了HTML编程的基本方式,最后说到了表单提交的方式有get和post方式.那么究竟什么是get/post 方式呢,两者有什么差别?如今我就详细的介绍一下. 首先回想一下表单的 ...
- Linux Terminal fortune
Linux下,我们能够使用apt-get安装fortune,这是一个比較有趣的功能 在输入fortune之后,Terminal会输出一句名言.诗句,或一些有趣的话: 默认情况下.fortune仅仅会显 ...
- Google面试题-高楼扔鸡蛋问题
本文由 @lonelyrains 出品.转载请注明出处. 文章链接: http://blog.csdn.net/lonelyrains/article/details/46428569 高楼扔鸡蛋问 ...
- 开源工作流BPM软件JFlow安装配置视频教程
上周上传了一次,被抽了.刚開始不知道CSDN没有视频许可.造成一些爱好者无法下载,对此感到羞愧. 在下载后,依照文档内的连接,直接取出来就能够了,包括文档说明.视频教程两部分. http://down ...
- shell学习五十天----查看进程ps命令
进程列表 列出进程中最重要的命令便是进程状态命令:ps. ps命令是进程状态(Process Status)的缩写.ps命令用来列出系统中当前执行的那些进程.ps命令列出的是当前那些进程的快照,就是执 ...
- 将linux下的rm命令改造成移动文件至回收站
将linux下的rm命令改造成移动文件至回收站 rm是Linux下文件删除的命令,它是Linux下非常强大却又非常危险的一条命令,特别是rm -rf有时候强大到让你欲哭无泪,当你想清除当前目录下的所有 ...
- springAOP注解方式实现日志操作
通过自定义注解调用方法执行日志存储: package com.zktx.platform.log2; import java.lang.reflect.Method; import java.util ...