前端基础进阶(五):全方位解读this
https://segmentfault.com/a/1190000012646488 https://yangbo5207.github.io/wutongluo/
说明:此处只是记录阅读前端基础进阶的理解和总结,如有需要请阅读上面的链接
一、this的指向在执行上下文的创建阶段确定,即是在函数的调用阶段确定的,因此不同的调用方式this的指向可能不同
var a = 10;
var obj = {
a: 20,
GetA:function(){
console.log(this.a);
}
} obj.GetA(); //
var f = obj.GetA;
f();//
f()独立调用,this指向全局环境;obj.GetA()不是独立调用,this指向函数所属的对象。 关于this指向的结论:在一个函数的全局上下文中,this用调用者提供,由函数的调用方式决定。如果函数被调用时被某一个对象所拥有(即写法如obj,GetA()),那么函数内部的this指向改对象;
如果函数是独立调用,那么内部的this指向undifined。在非严格模式下当this指向undefined时,它会被自动指向全局对象。 注意事项:全局环境中的this指向全局环境本身,this指向在函数执行过程中不能改变,所以给this赋值会报错,如this=obj; 说明:this指代的是对象,函数中的this并不是表示函数作用域。如下例子刚开始以为输出a=10,a表示函数fn的作用范围,其实不是a表示的是全局对象。
var a = 20;
function fn() {
var a=10;
function foo() {
console.log(this.a);
}
foo();//独立调用,所以输出结果还是20
}
fn();
严格模式下的foo()是独立调用,this指向undifined,故this.a报错,而window.foo()不是独立调用,this指向window,所以this.a=20,故结果40
'use strict';
var a = 20;
function foo() {
var a = 1;
var obj = {
a: 10,
c: this.a + 20,
fn: function () {
return this.a;
}
}
return obj.c; }
console.log(window.foo()); //
console.log(foo()); // TypeError: this is undefined
三、使用call,apply显示指定this
JavaScript可使用call和apply方法手动设置函数中this的指向,每个函数都支持call和apply方法
var a = 10;
var obj={
a:10
}; function fn() {
console.log(this.a);
} fn.call(obj);//
call和apply的用法
第一个参数为this的指向,剩下的参数是函数本身的参数,区别是call方法中函数参数是一个一个传入,apply方法以数组方式传入
var a = 10;
var obj={
a:10
}; function fn(num1,num2) {
console.log(num1+num2+this.a);
} fn.call(obj, 1, 2); //
fn.apply(obj, [1, 2]); //
四 call/apply的用途
1.将类数组转换为数组
function add(num1, num2, mum3) {
console.log(arguments); //打印出类数组原来的样子Arguments { 0: 1, 1: 2, 2: 3, … }
var arg = [].slice.call(arguments); //把类数组转换成数组 Array [ 1, 2, 3 ]
console.log(arg);
}
add(1, 2, 3);
2.根据自己需要灵活指定this
var foo = {
name: 'joker',
showName: function () {
console.log(this.name);
}
}
var bar = {
name: 'rose'
}
foo.showName.call(bar);//rose
3.实现继承
//定义父级构造函数
var Person = function (name, age) {
this.name = name;
this.age = age;
} //定义子类构造函数
var Student = function (name, age, high) {
Person.call(this, name, age);
this.high = high;
} Student.prototype.message = function () {
console.log('name:' + this.name + 'age:' + this.age + 'high:' + this.high);
} var stu = new Student('xiaoming', 10, '150cm');
stu.message(); //name:xiaomingage:10high:150cm
要理解上面的例子,首先要搞清楚构造函数中this的指向。this指向是在函数调用时确定的,所以要弄明白构造函数中的this指向就要搞清楚new之后经历了什么。
调用new运算符之后会经历一下阶段:
1)创建一个新的对象
2)将构造函数中的this指向这个新的对象
3)执行构造函数的代码为这个新对象添加属性,方法等
4)返回新对象
上面的例子在Student的构造函数中利用call方法把新创建的对象传递给Person,从而给新对象添加name,age属性,也就相当于实现了继承。
4.保存this指向正确的对象
var a = 20;
var obj = {
a:10,
getA:function(){
setTimeout(function(){
console.log(this.a);
},1000);
}
}
obj.getA();//
上例本意是想打印出对象obj中a的值,但是由于setTimeout函数的存在,导致实际执行的时候this指向了全局对象,所以打印结果是20。
注意:setTimeout的作用是向JavaScript注册函数,并在指定时间之后执行注册的函数,因此等到函数运行时这个函数就相当于是独立调用,this在费严格模式下自动指向全局对象。
最简单的改法是利用闭包把this指向的对象保存下来
var a = 20;
var obj = {
a: 10,
getA: function () {
var self = this;
setTimeout(function () {
console.log(self.a);
}, 1000);
}
}
obj.getA();//
另一个方式是使用call或者apply封装一个bind方法,确保函数指向obj
var a = 20;
var obj = {
a: 10,
getA: function () { setTimeout(bind(function () {
console.log(this.a);
},this), 1000);
}
} function bind(fn, obj) {
return function () {
fn.call(obj); //或者fn.apply(obj);
}
} obj.getA();//
还可以用JavaScript自带的bind方法,作用是把函数fn.bind(obj)的this指向绑定到obj
var a = 20;
var obj = {
a: 10,
getA: function () { setTimeout(function () {
console.log(this.a);
}.bind(this), 1000);
}
} obj.getA();//
前端基础进阶(五):全方位解读this的更多相关文章
- 前端基础进阶(十五):详解 ES6 Modules
对于新人朋友来说,想要自己去搞定一个ES6开发环境并不是一件容易的事情,因为构建工具的学习本身又是一个非常大的方向,我们需要花费不少的时间才能掌握它. 好在慢慢的开始有大神提供了一些非常简单易懂,学习 ...
- 前端基础进阶(七)-前端工程师最容易出错的问题-this关键字
我们在学习JavaScript的时候,因为对一些概念不是很清楚,但是又会通过一些简洁的方式把它给记下来,那么这样自己记下来的概念和真正的概念产生了很强的偏差. 当然,还有一些以为这个是对的,还会把它发 ...
- 前端基础进阶(十四):es6常用基础合集
在实际开发中,ES6已经非常普及了.掌握ES6的知识变成了一种必须.尽管我们在使用时仍然需要经过babel编译. ES6彻底改变了前端的编码风格,可以说对于前端的影响非常巨大.值得高兴的是,如果你熟悉 ...
- 前端基础进阶(十一):详细图解jQuery对象,以及如何扩展jQuery插件
早几年学习前端,大家都非常热衷于研究jQuery源码.我还记得当初从jQuery源码中学到一星半点应用技巧的时候常会有一种发自内心的惊叹,“原来JavaScript居然可以这样用!” 虽然随着前端的发 ...
- 前端基础进阶(六):在chrome开发者工具中观察函数调用栈、作用域链与闭包
在前端开发中,有一个非常重要的技能,叫做断点调试. 在chrome的开发者工具中,通过断点调试,我们能够非常方便的一步一步的观察JavaScript的执行过程,直观感知函数调用栈,作用域链,变量对象, ...
- 前端基础进阶之Promise
前言 Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. 在实际的使用当中,有非常多的应用场景我 ...
- 转【前端基础进阶之Promise】
前言 Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. 在实际的使用当中,有非常多的应用场景我 ...
- 前端基础进阶(十三):透彻掌握Promise的使用,读这篇就够了
Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. 在实际的使用当中,有非常多的应用场景我们不能 ...
- 前端基础进阶(六)-大厂面试题问题:循环闭包与setTimeout
我在上一篇闭包的文章中留下了一个关于setTimeout与循环闭包的思考题. 利用闭包,修改下面的代码,让循环输出的结果依次为1, 2, 3, 4, 5 for (var i = 1; i <= ...
随机推荐
- 品尝阿里云容器服务:初步尝试ASP.NET Core Web API站点的Docker自动化部署
部署场景是这样的,我们基于 ASP.NET Core 2.0 Preview 1 开发了一个用于管理缓存的 Web API ,想通过阿里云容器服务基于 Docker 部署为内网服务. 在这篇博文中分享 ...
- VMware与Centos系统安装 和重置root密码
VMware与Centos系统安装 今日任务 1.Linux发行版的选择 2.vmware创建一个虚拟机(centos) 3.安装配置centos7 4.xshell配置连接虚拟机(centos) ...
- python-----实现接口自动化测试(实例4)
实现接口自动化测试1.读取case---从测试用例Excel表格中读取接口请求数据2.调用接口---发送请求获取实际结果3.校验结果---实际结果与预期结果对比4.结果写入表格---将实际结果与测试状 ...
- URL编码问题
一般来说,URL只能使用英文字母.阿拉伯数字和某些标点符号,不能使用其他文字和符号. 比如,世界上有英文字母的网址"http://www.abc.com", 但是没有希腊字母的网址 ...
- Mysql 性能优化教程
Mysql 性能优化教程 目录 目录 1 背景及目标 2 Mysql 执行优化 2 认识数据索引 2 为什么使用数据索引能提高效率 2 如何理解数据索引的结构 2 优化实战范例 3 认识影响结果集 4 ...
- python实现斐波那契数列
https://www.cnblogs.com/wolfshining/p/7662453.html 斐波那契数列即著名的兔子数列:1.1.2.3.5.8.13.21.34.…… 数列特点:该数列从第 ...
- crm项目整理
crm项目整理 一.开发背景 由于公司人员的增多,原来通过excel表格存取方式过于繁琐,而且对于公司人员的调配和绩效考核等不能做到精确处理,所以开发crm系统,开始开发只是针对销售人员和客户,后 ...
- 2018/09/17《涂抹MySQL》【性能优化及诊断】学习笔记(七)
读 第十三章<MySQL的性能优化与诊断> 总结 一说性能优化,整个人都像被打了鸡血一样
- idea 在tomcat启动的时候发现控制台输出的是乱码
先前觉得是tomcat的问题,后来发现是idea的问题: 打开IntelliJ IDEA本地安装目录中bin文件夹下的idea.exe.vmoptions和idea64.exe.vmoptions这两 ...
- Python摸爬滚打之day04----基本数据类型(列表,元组)
1.列表 列表是可变的, 有序的数据类型,列表是按照添加顺序来保存的,可以存放各种数据类型. 1.1 列表的切片(同字符串) 1.2 列表的增删改查 注意: 列表是可以直接在列表上面进行操 ...