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 ...
随机推荐
- 【Java】基本类型和引用类型(值传递)
[关键词] [问题] · 加深对基本类型和引用类型的理解: [效果图] [分析] 參见最后的[參考资料] [解决方式] [代码] public void test() throws Exception ...
- Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader
Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader 之前写了两篇文章,介绍了我在边缘检測上面的研究.实际上.使用GPU对渲染图像进行边缘检測.前提是须要进行两遍渲染.前 ...
- Python查询数据库,中文的结果显示不出来
表里面的数据: 问题:查询数据库,返回结果不是中文可以,是中文的话就报错UnicodeEncodeError: 'gbk' codec can't encode character '\xd4' in ...
- Linux系统的命令源码的获取方法
我们知道,Linux是开源的,它自带的功能强大的命令也是开源的,也就是说.我们能够获得这些命令的源码并研究它.那到底怎样获得系统的命令的源码呢? 命令的源码是一个软件包为单元的,放在一个软件包的源码中 ...
- cmd执行调用打开文件
Process p = new Process();//新进程 p.StartInfo.FileName = "cmd.exe";//打开cmd程序 p.StartInfo.Use ...
- thinkphp 具体常量,在view里面使用
1 2 3 4 5 6 7 8 9 '__TMPL__' => APP_TMPL_PATH, // 项目模板目录 '__ROOT__' => __ROOT__, ...
- javascript设计模式-掺元类
有一种重用代码的方法不需要用到严格的继承.如果想把一个函数用到多个类中,可以通过扩充的方式让这些类共享该函数.其实际做法大大体为:先创建一个包含各种通用方法的类,然后再用它扩充其他的类.这种方式就叫做 ...
- 认识React框架
在大厂面试的时候被问会不会React框架几乎是必须的,可见React框架在现在前端市场的份额.所以说学习React框架的必要性. react框架起源于Facebook的内部项目,因为对市场上的Java ...
- Ajax请求成功但是一直进入error的原因
1.在1.3版本的jQuery以后,严格要求了json格式,如果返回的值不是json格式,他就会执行error函数. 所以如果想让他走success函数的话,还是在后台把数据格式化成json格式吧. ...
- NOIP 2014 T2 联合权值 DFS
背景 NOIP2014提高组第二题 描述 无向连通图G有n个点,n-1条边.点从1到n依次编号,编号为i的点的权值为Wi ,每条边的长度均为1.图上两点(u, v)的距离定义为u点到v点的最短距离.对 ...