JavaScript允许在函数内部,引用当前执行中环境的其他变数。
function func() {
console.log(a)
}
如上代码,func函数引用了当前执行环境的a,问题是这个函数可以在任何执行环境中被调用,因此这时候的a可能就指向不同了,所以JS引擎需要有一个机制,可以依靠其优雅的、准确地指向当前代码运行的执行环境。
//假设这个object名称很长,且有可能改名
let objectWithALongName={
name:"David",
func1(){
return objectWithALongName.name;
},
func2(){
return this.name;
}
}
objectWithALongName的方法func2使用了this关键字,就优雅多了,然後即使往後对象名称改变了,func2内部代码也不需改变。
另外如果有其他执行环境也需要使用到这个函数,使用this也可以优雅的指向该执行环境:
let otherObject = {
name:"John",
cloneMethod:objectWithALongName.func2
}
otherObject.cloneMethod(); // John func2中的this这时候指到otherObject
this可以精准的指向某个对象。
//全域变数
let objectWithALongName = {
name: "David"
};
(function() {
//局部变数
let objectWithALongName = {
name: "John",
func1() {
return objectWithALongName.name;
},
func2() {
//相对於func1,这边用了this可以清楚知道指向内部IIFE的执行环境
return this.name;
}
};
console.log(objectWithALongName.func1());// John
})();
呼叫位子就是函数在代码中在哪里被调用,而不是声明的位子。所以搞清楚「由谁在哪调用」才能精确的找到this的指向。
let module = {
id: 10,
getId: function() {
return this.id;
}
}
console.log(module.getId());//>> 10
let globalGetId = module.getId;//getX和module.getX都是指向记忆体中函数的地址而已,这边并没有被()执行
console.log(globalGetId()); //>> undefined
作为module对象的getId方法被调用,this指向module,module对象有一个属性id值为10,所以console.log(module.getX())出10,而globalGetId中的this会指向全域,全域中并没有定义id,所以出undefined。
-->This既不指向函数自身,也不指向函数的作用域
let obj = {
a:"123"
}
function func() {
this = obj; //报错,因为在执行阶段试图改变this
console.log(this.a);
}
func();
function func() {
console.log( this.a ); // this指向全域对象
}
let a = 2;
func(); // 2
对於默认指向来说,决定this指向的并不是调用位置是否是严格模式(use strict),而是函数本体是否处於严格模式。如果函数处於严格模式,this指向undefined,否则指向全域。
function func() {
"use strict";//函数中处於严格模式下,this指向undefined
console.log(this.a);
}
let a = 123;
func(); // 报错
function func() {
console.log(this.a);
}
var a = 123;
(function() {
"use strict";
func(); // 123
})();
隐式指向是日常开发中最常见的,也就是决定this指向的是由谁呼叫,与函数存在的位置无关:
function func() {
console.log(this.a);
}
let obj = {
a: 2,
func: func
};
obj.func(); // 2
// 找到呼叫位置,由obj对象来呼叫函数func,
// 此时可以说函数func被呼叫时,obj对象拥有或者包含func函数
// 所以此时的 this 指向呼叫 func 函数的 obj 对象。
对象属性引用链中只有最顶层或者说最後一层才会影响调用位置,简单说,this指向最靠近被调用函数的对象。
function func() {
console.log(this.a);
}
let obj2 = {
a: 10,
func: func
};
let obj1 = {
a: 20,
obj2: obj2
};
// this指向obj2对象,因为obj2离的最近
obj1.obj2.func(); // 10
Javascript内建对象Function的三种原型方法call()、apply()、bind(),他们的第一个参数是对象,他们会把这个对象绑定到this,接着在调用函数时让this指向这个对象。
let a = 10;
function func() {
console.log( this.a );
}
let obj = {
a:20
};
func.call(obj); // 20
// 在呼叫func时强制把this指向obj
使用new来调用函数,或者说发生构造函数调用时,会执行底下操作 :
function func(a) {
this.a = a;
}
let bar = new func("test");
console.log(bar.a); // test
// 使用new 来呼叫func(..)时,创建一个新对象并把它绑定到func(..)调用中的this上
另外一个观点:
function User(name) {
// this = {};(隐藏创建)
// 添加属性到 this
this.name = name;
this.isAdmin = false;
// return this;(隐藏返回)
}
用以上介绍规则可以简单做一个判断流程:
如果是的话,this绑定的是新创建的对象。
function func(name) {
this.name = name;
this.getName = function() {
return this.name;
};
}
let obj = new func("apple"); //this会指向obj
console.log(obj.getName()); // apple
let obj1 = {
name: "David"
};
function func() {
return this.name; //这里的this本来指向window
}
let str = func.call(obj1); //改变了func函数里面this的指向,指向obj1
console.log(str); // David
let obj1 = {
name: "Jack",
func() {
return this.name; //指向obj1
}
};
//这里的obj1.func(),表明func函数被obj1调用,因此func中的this指向obj1
console.log(obj1.func()); // Jack
如果在非严格模式下,就绑定到全域对象。
let a = 123; //为全域对象增加一个变数a
function func() {
return this.a;
}
console.log(func()); // 123
<<: day7: CSS style 规划 - CSS in JS(emotion 使用 - 1)
简介 上一篇介绍了如何利用2进位来表示10进位的数字,这次则要再进阶的介绍一下4、8、16进位。在下...
Intro 这次是写了两个小游戏,并从里面学到一点 member function 的用法,还有字串...
案例说明及适用场景 组织架构是由部门及职务做为骨架,员工就职於某一个职务 员工在企业的职务,就如同系...
前情提要 前三篇文章带各位开发了一只 PTT 爬虫,具备持续爬取,并将爬取到的文只内容储存於 JSO...
小夜灯 ( 光敏电阻 ) 教学原文参考:小夜灯 ( 光敏电阻 ) 虽然 micro:bit 有内建侦...