鍍金池/ 問(wèn)答/HTML/ javascript關(guān)于this的一個(gè)問(wèn)題

javascript關(guān)于this的一個(gè)問(wèn)題

function Person(){
  this.say = function(){
    console.log("Hello");
  };
}
var person = new Person();
person.say();

這應(yīng)該是一個(gè)奇怪的問(wèn)題,為什么可以通過(guò)person.say的方式訪問(wèn)say方法。
好像把this去掉,就不能正常輸出結(jié)果了。這個(gè)this有什么作用。

我在判斷this指代誰(shuí)的時(shí)候總會(huì)告訴自己誰(shuí)調(diào)用指代誰(shuí),而這次,this直接出現(xiàn)在了say前面,我有點(diǎn)糊涂了,感覺(jué)自己沒(méi)辦法表達(dá)清楚自己的問(wèn)題。

回答
編輯回答
終相守

1.new操作符的作用是把后面的函數(shù)當(dāng)做構(gòu)造函數(shù),創(chuàng)造一個(gè)對(duì)象,然后把this指針指向這個(gè)對(duì)象,同時(shí)返回這個(gè)對(duì)象
2.所以這里的this就是指向new出來(lái)的對(duì)象,如果去掉了this,那么這個(gè)方法就不屬于new出來(lái)的對(duì)象,而只屬于Person這個(gè)函數(shù)的內(nèi)部作用域,外部訪問(wèn)不了

2017年10月19日 09:51
編輯回答
念舊

先來(lái)看一段 ES6 class 語(yǔ)法的例子

class Person {
    say() {
        console.log("hello");
    }
}

const person = new Person();
person.say();

上面這是采用 class 語(yǔ)法定義的 Person 類,它有一個(gè) say() 方法。運(yùn)行效果和題主的代碼運(yùn)行效果一致,但本質(zhì)上還是有些區(qū)別。這段代碼里看不到 this,而 say() 方法也不是定義在 Person 的每個(gè)實(shí)例對(duì)象上,而是定義在 Person 的原型對(duì)象中。

如果要把題主的代碼翻譯成 class 語(yǔ)法,應(yīng)該是這樣:

class Person {
    constructor() {
        this.say = function() {
            console.log("hello");
        };
    }
}

const person = new Person();
person.say();

這里出現(xiàn)了 constructor,即構(gòu)造函數(shù)。構(gòu)造函數(shù)中,通過(guò) this 指針對(duì)實(shí)例對(duì)象添加了一個(gè) say() 方法。如果有多個(gè)實(shí)現(xiàn),每個(gè)實(shí)例都有自己的 say() 方法實(shí)例,雖然行為一樣,但卻是不同的對(duì)象,可以驗(yàn)證一下

class Person {
    constructor() {
        this.say = function() {
            console.log("hello");
        };
    }
}

const person = new Person();
const p2 = new Person();
console.log(person.say === p2.say);
// false

這里提到了構(gòu)造函數(shù)。在 ES6 以前,需要定義 JavaScript 類,就是通過(guò)構(gòu)造函數(shù)來(lái)定義的,然而實(shí)際上,構(gòu)造函數(shù)和普通函數(shù)在定義上并沒(méi)有多大區(qū)別,當(dāng)調(diào)用的時(shí)候使用了 new 運(yùn)算符,就是構(gòu)造,沒(méi)使用,就是普通函數(shù) 參閱:JavaScript 的 this 指向問(wèn)題深度解析。

OOP 語(yǔ)言在產(chǎn)生對(duì)象的時(shí)候一般都是這么一個(gè)過(guò)程:產(chǎn)生一個(gè)對(duì)象,從最遠(yuǎn)的基類開(kāi)始依次調(diào)用變量初始化(如果有的話)和構(gòu)造函數(shù),所以調(diào)用構(gòu)造函數(shù)的時(shí)候,已經(jīng)存在對(duì)象,this 指針已經(jīng)生效,可以在構(gòu)造函數(shù)中使用 this 指針。對(duì)于靜態(tài)語(yǔ)言來(lái)說(shuō),可以通過(guò) this 指針訪問(wèn)已經(jīng)定義的屬性,或者方法。而 JavaScript 是動(dòng)態(tài)語(yǔ)言,所以甚至可以使用 this 指針賦予它新的屬性,比如 this.say = ....,當(dāng)這個(gè)屬性是一個(gè)函數(shù)表達(dá)式的時(shí)候,就相當(dāng)于是在定義新的實(shí)例方法(非常確切的實(shí)例方法,每個(gè)實(shí)例一個(gè),各自不同)。

最后,既然是方法,那就可以使用 對(duì)象.方法() 的形式來(lái)調(diào)用,也就是 person.say()。如果沒(méi)有定義,當(dāng)然也就不能調(diào)用了,也就是題主說(shuō)的沒(méi)效果(實(shí)際應(yīng)該報(bào)錯(cuò))

2017年12月20日 16:52
編輯回答
茍活

這個(gè)問(wèn)題很好!這個(gè)問(wèn)題其實(shí)闡述了javascript十分核心的知識(shí)點(diǎn):面向?qū)ο缶幊?/code>。從三個(gè)方面說(shuō)說(shuō)面向?qū)ο缶幊蹋?code>對(duì)象、構(gòu)造函數(shù)new 命令。

一、對(duì)象

對(duì)象是單個(gè)實(shí)物的抽象,也可以說(shuō)是一個(gè)容器,里面包含對(duì)象屬性和對(duì)象方法。

二、構(gòu)造器

構(gòu)造函數(shù)是專門(mén)用來(lái)生成對(duì)象的函數(shù)。
function Person() {...}。這里Person函數(shù)其實(shí)就是一個(gè)構(gòu)造函數(shù)!其中構(gòu)造函數(shù)一般有兩個(gè)特點(diǎn):1、構(gòu)造函數(shù)體內(nèi)部使用了this關(guān)鍵字,代表了所要生成的對(duì)象實(shí)例。2、用new命令生成對(duì)象。

三、new 命令

new命令的作用,就是執(zhí)行構(gòu)造函數(shù),返回一個(gè)實(shí)例對(duì)象。
var person = new Person();這里通過(guò)new命令,讓構(gòu)造函數(shù)Person生成了一個(gè)實(shí)例對(duì)象,并保存在變量person中,這個(gè)新生成的實(shí)例對(duì)象,從構(gòu)造函數(shù)Person繼承了say方法,new命令執(zhí)行時(shí),構(gòu)造函數(shù)內(nèi)部的this,就代表了新生成的實(shí)例對(duì)象,this.say表示實(shí)例對(duì)象有一個(gè)say方法。如果去掉this,say方法就變成了局部方法,外部是無(wú)法調(diào)用的。
2018年1月12日 18:44