zoukankan      html  css  js  c++  java
  • Javascript中的this指向

    this 相关讨论

    this 作为关键词在 js 中有着相当重要的作用, 我们这次主要讨论一下 this 在不同情况下的指向

    作为普通函数调用

    我们知道, 在函数执行代码之前会初始化自己的作用域, 此时就有两个重要的角色生成, 一个是 this,另一个是 'arguments', 我们这次只讨论 this, 如果仅仅是函数的调用, 此时的 this 是指向 window 对象, 在严格模式下 thisundefined

    (function() {console.log(this === window);}());	// true;
    (function() {'use strict'; console.log(this === undefined);}()); //true
    

    作为构造函数调用

    当我们使用 new 操作符去调用一个对象的时候 this 指向实例化的对象, 这点比较常见, 此时最好不要去用 return 出一个引用类型的值去替代 this 返回

    console.log(new (function(a) {this.a = a;})(1));	// {a: 1}
    

    作为箭头函数调用

    这种用法在我们的分享 函数的拓展 (孙凡云分享)中有讲, 在此不细说, this 指向该方法的作用域中的 this

    ( x => (x => console.log(this === window))() )();			// true
    ( x => (x => console.log(this === window)).bind({})() )();	// true
    

    箭头函数无视 bind 等类似方法, 使用时要注意这点

    作为对象的方法调用

    在定义对象的时候, 如果某个键的值是 Function 类型我们称这样的键是方法, 当对象调用自己的方法时, 该方法内部的 this 便指向了对象自己

    ({
    	color: 'red', 
    	showColor: function() {console.log(this.color)}
    }).showColor();			// red;
    

    apply, call, bind 时

    这三种调用方式对 this 的影响是一样的, this 的具体指向和传入的第一个参数有关, 非严格模式下程序执行的时候会对第一个入参进行一个类型转换, js 尝试将其转换成其对应的包装类型, 如果转化失败 this 就指向 window
    , 严格模式下不进行转换, this 指向传入的第一个参数

    (function(){
    	var foo = function() {
    		'use strict';
    		console.log(this);	
    	};
    
    	(function() {
    		foo.call(1);				// 1
    		foo.call('hello world');	// hello world
    		foo.call(true);				// true
    		foo.call(null);				// null
    		foo.call(undefined);		// undefined
    		foo.call({});				// {}
    	}());
    
    	foo = function() {
    		console.log(this);	
    	};
    
    	(function() {
    		foo.call(1);				// 1的包装类型, 即 new Number(1), 下面一样
    		foo.call('hello world');	// 'hello world'的包装类型
    		foo.call(true);				// true的包装类型
    		foo.call(null);				// null无包装类型, window
    		foo.call(undefined);		// undefined无包装类型, window
    		foo.call({});				// {}
    	}());
    }());
    
    

    大家验证上面的 Demo 的时候注意里面的分号, 我使用的这种写法里面的分号不能随意省略;

    bind 后的函数

    一旦函数被 bind 了, 那么它里面的 this 便已 认主 了, 无法再次修改

    let foo = function() {
    	console.log(this);
    };
    
    let obj = { a: 1 };
    
    let bar = foo.bind(obj);
    
    let oth = bar.bind({});
    
    bar(), oth();	// {a: 1} 	{a: 1}
    

    一些其他的场景

    下面说的这些场景都能利用上面的知识进行分析, 只是写法有些不一样, 道理还是上面讲的部分

    var x = 1;
    
    var obj = {
    	x: 100,
    	showX: function() {
    		console.log(this.x);
    	}
    };
    
    let showX = obj.showX;
    
    showX();					// 1
    (obj.showX)();				// 100
    (obj.showX = obj.showX)();	// 1
    (x => obj.showX)()(); 		// 1
    (x => obj.showX.bind(this))().call(obj); // 1
    

    这几种写法虽然不常见, 但是仔细想想弄清楚为什么, 能够帮助我们理解 this 的具体指向, 在项目中也能减少使用 let self = this 的次数

    小结

    1. 作为普通函数调用, 分为严格模式和非严格模式
    2. 作为构造函数调用, this 指向实例
    3. 作为箭头函数调用, this 指向包裹该方法的作用域中的 this, 无视绑定
    4. 作为对象的方法调用, 指向调用该方法的对象
    5. bind, 区分严格模式和非严格模式, 具体情况见上面
  • 相关阅读:
    git 远程仓库 and 分支管理
    oracle 导入导出dmp
    sql if else 用法
    设置session超时的三种方式
    eclipse定制工具栏,修改工具栏
    cxf实例异常
    js 表格插入指定行
    iframe 调用父页面元素
    iframe页面刷新
    frame 和 iframe
  • 原文地址:https://www.cnblogs.com/idiv/p/8442873.html
Copyright © 2011-2022 走看看