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 ...
随机推荐
- 0709MySQL 数据库性能优化之表结构优化
转自http://isky000.com/database/mysql-perfornamce-tuning-schema MySQL 数据库性能优化之缓存参数优化 MySQL数据库性能优化之硬件瓶颈 ...
- cogs 10. 信号无错传输
10. 信号无错传输 ★★☆ 输入文件:dlj.in 输出文件:dlj.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 为提高传递信息的保密性和可靠性,两个军事 ...
- 反射常用API
反射所有功能都是通过class API来实现的 class常用API有: 1.class.GETINTERFACES():获得这个类实现的接口. 2.class.getMethods() Method ...
- Java枚举类型使用示例
Java枚举类型使用示例 学习了:https://www.cnblogs.com/zhaoyanjun/p/5659811.html http://blog.csdn.net/qq_27093465/ ...
- mysql查询count
Every derived table must have its own alias 每个派生出来的表都必须有一个自己的别名 一般在多表查询时,会出现此错误. 因为,进行嵌套查询的时候子查询出来的的 ...
- Codeforces Round #244 (Div. 2)D (后缀自己主动机)
Codeforces Round #244 (Div. 2)D (后缀自己主动机) (标号为0的节点一定是null节点,不管怎样都不能拿来用,切记切记,以后不能再错了) 这题用后缀自己主动机的话,对后 ...
- Linux中的默认权限与隐藏权限(文件、文件夹)
一个文件(或文件夹)拥有若干个属性.包含(r/w/x)等基本属性,以及是否为文件夹(d)与文件(-)或连接文件(l)等属性.此外,Linux还能够设置其它系统安全属性.使用chattr来设置.以lsa ...
- 国外物联网平台初探(五) ——Exosite Murano
定位 Murano是一个基于云的IoT软件平台,提供安全.可扩展的基础设施,支持端到端的生态系统,帮助客户安全.可扩展地开发.部署和管理应用.服务以及联网产品. 功能 Murano平台简化了整个IoT ...
- 深入解析Dropout——基本思想:以概率P舍弃部分神经元,其它神经元以概率q=1-p被保留,舍去的神经元的输出都被设置为零
深度学习网络大杀器之Dropout——深入解析Dropout 转自:https://yq.aliyun.com/articles/68901 摘要: 本文详细介绍了深度学习中dropout技巧的思想 ...
- Dragon Ball--hdoj
Dragon Ball Problem Description Five hundred years later, the number of dragon balls will increase u ...