suchen

Heim  >  Fragen und Antworten  >  Hauptteil

Javascript – Probleme damit und Konstruktoren in JS

function People() {
}
People.prototype.say = function () {
    alert("hello");
}

function Student() {
}
Student.prototype = new People();
var superSay = Student.prototype.say;

Student.prototype.say = function () {
    superSay.call(this);            // 为什么会是"hello"?
    alert("stu-hello");
}
var s = new Student();
s.say();

Wie im Code kommentiert, auf wen zeigt superSay.call(this)为什么会是People.prototype.say函数被调用?this?

我想大声告诉你我想大声告诉你2711 Tage vor765

Antworte allen(5)Ich werde antworten

  • 曾经蜡笔没有小新

    曾经蜡笔没有小新2017-06-26 10:55:14

    this指向Student{}类,这个你可以在superSay.call(this)上面加一行console.log(this)进行验证。

    然后,我们看这个代码

    Student.prototype = new People();

    为了方便后面解释,我把这里的new People()创建的实例称为实例X
    由于superSay = Student.prototype.say,因为上面的Student.prototype = new People();,所以其中Student.prototype实例X
    所以实际上superSay调用的是实例Xsay,而并非People.prototype.say

    至于你为啥觉得是在调用People.prototype.say,主要还是原型链的问题。实例X是People类的一个实例,所以实例X的所有方法会从People类的原型链“继承”(用继承这个词,但是实际上JS的原型链和继承还是有些区别的)。所以实例X.say如果没有针对实例X重写say方法,那么实例Xsay就和People.prototype.say等效。

    另外,superSay.call(this)这个里面的call,只是改变了this的上下文而已。但是由于superSay实例X.say,这个方法里根本没有this,所以this上下文的修改并不影响运行的结果。

    Antwort
    0
  • 迷茫

    迷茫2017-06-26 10:55:14

    这个问题在js中经常遇见

    Antwort
    0
  • 代言

    代言2017-06-26 10:55:14

    个人观点:先说下查找say方法的查找顺序吧:s——student.prototype——people.prototype——Object,找到则就绪,停止查找。结合你的代码,say只会查找到student.prototype。这里可以先把你的代码先改成这样就比较清晰:

        People.prototype.say = function () {
            console.log(123);
        }
        People.prototype.jiao = function () {
            console.log(456);
        }
        Student.prototype.say = function () {
              console.log(321)
        }

    其他不变。此时s.say()——输出321,s.jiao()——输出456。然后再回到你的代码,因为你这是重写了sdudent.prototype.say方法所以会执行此段代码

        Student.prototype.say = function () {
            superSay.call(this);            // 为什么会是"hello"?
            alert("stu-hello");
        }

    第一句superSay.call(this),首先superSay是一个变量,变量类型是function,你可以在 var superSay = Student.prototype.say后面加上一段代码console.log(typeof supperSay),于是你只是在调用这个函数,而这个变量储存的是Student.prototype.say。执行到var superSay = Student.prototype.say,其实这里赋值的是 People.prototype.say。这点在高程的166-167页有类似的。关于这点你可以再把你的代码这2段换成这样,其他不变。

        var superSay = Student.prototype.say;
        Student.prototype = new People();

    此时调用superSay 会报错,因为此时执行到var superSay = Student.prototype.say时;student.prototype只有一个constructer属性没有say方法。然后回到你的代码此时People.prototype.say会赋值给superSay

    综上第一句代码会输出hello,而你的call根本没什么用
    第二句就不用说了。
    关于this其实我也不是特别清楚。我原来还认为console.log(this)会输出S,结果输出student,还需继续学习。
    

    Antwort
    0
  • 我想大声告诉你

    我想大声告诉你2017-06-26 10:55:14

    把superSay构造函数中的this绑定为Student.prototype.

    Antwort
    0
  • PHP中文网

    PHP中文网2017-06-26 10:55:14

    楼上扯这么多不怕楼主蒙圈吗

    他程序里面stuSay指向的是function () {alert("hello");} 这个匿名函数对象,只要你不重新赋值stuSay,他一直就是指向这个函数对象,管你在什么地方调用,永远就是这么个结果,至于在函数体内部this指向谁,你看下犀牛书吧....

    楼主把犀牛书函数部分看完就不会有这些问题了,至于楼上扯那么多,真别把楼主扯晕了

    Antwort
    0
  • StornierenAntwort