zoukankan      html  css  js  c++  java
  • 浅析js中的this

    this的用法

    this在日常javascript编码中很常见, 但是一直以来没有好好总结过。 今天在这里好好总结一下。 本文只讨论浏览器环境。

    this指向全局

    var name = "window";
    function foo() {
    	var name = "local";
    	console.log(this.name);
    }
    foo(); 
    

    相信这段代码大家都看到过,在这里this指向了全局,输入结果是"window".一开始我也不理解为什么有些时候this是指向内部函数,有些时候是指向window了。 相信好多小伙伴都和我一样比较疑惑, 后来我去翻阅犀牛书,犀牛书对函数this的解释是:关键字this没有作业域限制, 嵌套的函数不会从调用它的函数中继承this如果函数嵌套作为方法调用其this的值指向调用它的对象。 如果嵌套函数作为函数调用,其this不是全局对象(非严格模式下)就是undefined(严格模式下)。

    其实总结一下这段话就是: 一个函数如果是执行而不是作为一个对象的方法来使用,
    那么它就指向全局对象或者undefined。 所以这就解释了第一段代码。

    那接下来我们解释第二个结论:

    作为对象的方法使用。

    var name = "window";
    function foo() {
    	var name = "local";
    	console.log(this.name);
    }
    var obj = {
    	name: 'local',
    	foo: foo
    };
    obj.foo(); 
    

    根据上面的结果, 我们很容易得出这里的this就指向了对象obj。在一些称谓中,这个叫做this的隐式绑定。

    call,apply 对this的显式绑定

    个人不喜欢文字堆砌,还是直接上代码吧。

    var name = "window";
    var obj = {
    	name: "obj"
    };
    function foo() {
    	console.log(this.name);
    }
    foo(); //直接调用函数 this指向window
    foo.call(obj); //改变函数的上下文,把obj传进去
    

    这里显式绑定了函数的上下文,让this指向了obj,结果输入为“obj”

    顺带提一下,call,apply的区别,面试题经常被问。

    使用call或者apply让一个函数以一个对象的方法执行,第一个参数是指定上下文,可以是一个对象也可以是null。

    call和apply区别是第二个参数,apply是数组的形式传参。

    this在构造函数的使用

    this的构造函数中使用蛮多的,也蛮方便的。

    function Foo() {
    	this.a = "foo";
    }
    var f = new Foo();
    console.log(f.a); 
    

    通过new一个函数,那么在构造函数中,this指向实例化的对象f。

    上面说完了理论知识,那么我们来几个应用场景题

    example 1:
    var name = "window";
    function foo() {
    	console.log(this.name);
    }
    var obj = {
    	name: 'obj',
    	foo: foo
    };
    var a = obj.foo;
    a();
    obj.foo = null;
    a(); 
    

    可能有些同学会认为function也是对象,对象的复制是引用类型复制,那么只是指向obj.foo,如果obj.foo置空了,那么a也就不能输出this.name了。其实结果不是的,函数的复制是值的复制,和数组复制造成引用或者其他的引用不一样。简单点说

    a = obj.foo = function {
        console.log(this.name);
    }
    

    那么,现在执行a(); 和obj里面的foo函数还没有任何关系了。既两次执行结果都是'window';

    example 2:

    看完上面这个例子,同样的我们有些是经常使用回调函数,把函数当一个参数传递,那这个参数是不是也是值的复制?请看下面的例子。

    function aaa(fn) {
    	fn();
    }
    
    function foo() {
    	console.log(this.name);
    }
    
    var obj = {
    	name: 'obj',
    	foo: foo
    };
    
    aaa(obj.foo);
    

    如果看不懂这个的话 ,这里也可以简化一下

    function aaa(fn) { //在参数这里 可以理解为 var fn = obj.foo;
    	fn(); 
    }
    

    从例子1中我们可以知道函数是值的复制,那必然在aaa里面执行另外一个函数,而不是执行一个函数的方法,结果仍然是'window'.

    example 3:
    var name = "window";
    setTimeout(function(){
    	var name = "local";
    	console.log(this.name);
    },1000);
    

    相信大家经常用定时器吧,那么有没有踩过这个坑,在定时器中,this是指向全局window的。

    因为setTimeout是window下面的方法。代码可以转换为:

    var name = "window";
    window.setTimeout(function(){
    	var name = "local";
    	console.log(this.name);
    },1000);
    

    一个对象的方法使用,那内部的this是指向这个方法,必然this指向了这个对象本身,既window。

    参考文档:

    javascript权威指南第六版

    晓婼:http://www.cnblogs.com/xiaoruo/p/4492453.html

  • 相关阅读:
    特斯拉PET钥匙-蓝牙无钥匙
    超声波倒车雷达
    KiCad层次原理图标签和引脚的操作
    Nuget常用命令
    TCP/IP协议入门
    unbuntu(18.04)下体验dotnet core
    c#中的异步
    Git的不完全使用指南
    c#语言特性8.0
    c#语言特性7.x
  • 原文地址:https://www.cnblogs.com/Aralic/p/4496982.html
Copyright © 2011-2022 走看看