素材牛VIP会员
javascript关于this的一个问题
 li***56  分类:JavaScript  人气:1060  回帖:3  发布于6年前 收藏
function Person(){
  this.say = function(){
    console.log("Hello");
  };
}
var person = new Person();
person.say();

这应该是一个奇怪的问题,为什么可以通过person.say的方式访问say方法。
好像把this去掉,就不能正常输出结果了。这个this有什么作用。

我在判断this指代谁的时候总会告诉自己谁调用指代谁,而这次,this直接出现在了say前面,我有点糊涂了,感觉自己没办法表达清楚自己的问题。

 标签:node.jsjavascript

讨论这个帖子(3)垃圾回帖将一律封号处理……

Lv5 码农
野***7 CEO 6年前#1

这个问题很好!这个问题其实阐述了javascript十分核心的知识点:面向对象编程。从三个方面说说面向对象编程:对象构造函数new 命令

一、对象

对象是单个实物的抽象,也可以说是一个容器,里面包含对象属性和对象方法。

二、构造器

构造函数是专门用来生成对象的函数。
function Person() {...}。这里Person函数其实就是一个构造函数!其中构造函数一般有两个特点:1、构造函数体内部使用了this关键字,代表了所要生成的对象实例。2、用new命令生成对象。

三、new 命令

new命令的作用,就是执行构造函数,返回一个实例对象。
var person = new Person();这里通过new命令,让构造函数Person生成了一个实例对象,并保存在变量person中,这个新生成的实例对象,从构造函数Person继承了say方法,new命令执行时,构造函数内部的this,就代表了新生成的实例对象,this.say表示实例对象有一个say方法。如果去掉this,say方法就变成了局部方法,外部是无法调用的。
Lv1 新人
飘***子 JS工程师 6年前#2

先来看一段 ES6 class 语法的例子

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

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

上面这是采用 class 语法定义的 Person 类,它有一个 say() 方法。运行效果和题主的代码运行效果一致,但本质上还是有些区别。这段代码里看不到 this,而 say() 方法也不是定义在 Person 的每个实例对象上,而是定义在 Person 的原型对象中。

如果要把题主的代码翻译成 class 语法,应该是这样:

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

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

这里出现了 constructor,即构造函数。构造函数中,通过 this 指针对实例对象添加了一个 say() 方法。如果有多个实现,每个实例都有自己的 say() 方法实例,虽然行为一样,但却是不同的对象,可以验证一下

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

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

这里提到了构造函数。在 ES6 以前,需要定义 JavaScript 类,就是通过构造函数来定义的,然而实际上,构造函数和普通函数在定义上并没有多大区别,当调用的时候使用了 new 运算符,就是构造,没使用,就是普通函数 参阅:JavaScript 的 this 指向问题深度解析。

OOP 语言在产生对象的时候一般都是这么一个过程:产生一个对象,从最远的基类开始依次调用变量初始化(如果有的话)和构造函数,所以调用构造函数的时候,已经存在对象,this 指针已经生效,可以在构造函数中使用 this 指针。对于静态语言来说,可以通过 this 指针访问已经定义的属性,或者方法。而 JavaScript 是动态语言,所以甚至可以使用 this 指针赋予它新的属性,比如 this.say = ....,当这个属性是一个函数表达式的时候,就相当于是在定义新的实例方法(非常确切的实例方法,每个实例一个,各自不同)。

最后,既然是方法,那就可以使用 对象.方法() 的形式来调用,也就是 person.say()。如果没有定义,当然也就不能调用了,也就是题主说的没效果(实际应该报错)

Lv1 新人
何***孽 软件测试工程师 6年前#3

1.new操作符的作用是把后面的函数当做构造函数,创造一个对象,然后把this指针指向这个对象,同时返回这个对象
2.所以这里的this就是指向new出来的对象,如果去掉了this,那么这个方法就不属于new出来的对象,而只属于Person这个函数的内部作用域,外部访问不了

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取