87,904
社区成员
发帖
与我相关
我的任务
分享
function Person(firstName) {
this.firstName = firstName;
}
// 在Person.prototype中加入方法
Person.prototype.walk = function(){
alert("I am walking!");
};
Person.prototype.sayHello = function(){
alert("Hello, I'm " + this.firstName);
};
// 定义Student构造器
function Student(firstName, subject) {
// 调用父类构造器, 确保(使用Function#call)"this" 在调用过程中设置正确
Person.call(this, firstName);
// 初始化Student类特有属性
this.subject = subject;
};
// 建立一个由Person.prototype继承而来的Student.prototype对象.
// 注意: 常见的错误是使用 "new Person()"来建立Student.prototype.
// 这样做的错误之处有很多, 最重要的一点是我们在实例化时
// 不能赋予Person类任何的FirstName参数
// 调用Person的正确位置如下,我们从Student中来调用它
Student.prototype = Object.create(Person.prototype); // See note below
// 设置"constructor" 属性指向Student
Student.prototype.constructor = Student;
// 更换"sayHello" 方法
Student.prototype.sayHello = function(){
console.log("Hello, I'm " + this.firstName + ". I'm studying " + this.subject + ".");
};
// 加入"sayGoodBye" 方法
Student.prototype.sayGoodBye = function(){
console.log("Goodbye!");
};
// 测试实例:
var student1 = new Student("Janet", "Applied Physics");
student1.sayHello(); // "Hello, I'm Janet. I'm studying Applied Physics."
student1.walk(); // "I am walking!"
student1.sayGoodBye(); // "Goodbye!"
// Check that instanceof works correctly
console.log(student1 instanceof Person); // true
console.log(student1 instanceof Student); // true
var arr = [];//想把每次创建的实例对象都自动放到arr数组中,好统一管理
function Parent() {
arr.push(this);
}
function Sub() {
this.name = "";
}
Sub.prototype = new Parent();//设置继承
alert(arr.length);//还没有创建实例对象,arr数组中就已经有一个了
var a = new Sub();
var b = new Sub();
alert(arr.length);//创建了两个实例对象,arr数组中还是只有一个
缺点二实例
function Parent() {
this.offset = {x:0, y:0};
}
function Sub() {
this.id = 123;
}
Sub.prototype = new Parent();//设置继承
var a = new Sub();
var b = new Sub();
a.offset.x = 200;
alert(b.offset.x);//对a.offset对象的修改,一起反映到b.offset对象上了
缺点三实例
function Parent(n) {
this.name = n;
}
function Sub(n,a) {
this.age = a;
}
Sub.prototype = new Parent();//设置继承
var a = new Sub("王五",26);//没有办法在实例化时给name传递参数。
var arr = [];//想把每次创建的实例对象都自动放到arr数组中,好统一管理
function Parent() {
arr.push(this);
}
function Sub() {
this.name = "";
}
Sub.prototype = new Parent();//设置继承
alert(arr.length);//还没有创建实例对象,arr数组中就已经有一个了
var a = new Sub();
var b = new Sub();
alert(arr.length);//创建了两个实例对象,arr数组中还是只有一个
缺点二实例
function Parent() {
this.offset = {x:0, y:0};
}
function Sub() {
this.id = 123;
}
Sub.prototype = new Parent();//设置继承
var a = new Sub();
var b = new Sub();
a.offset.x = 200;
alert(b.offset.x);//对a.offset对象的修改,一起反映到b.offset对象上了
缺点三实例
function Parent(n) {
this.name = n;
}
function Sub(n,a) {
this.age = a;
}
Sub.prototype = new Parent();//设置继承
var a = new Sub("王五",26);//没有办法在实例化时给name传递参数。
[/quote]
针对第三个问题,我认为是这样的,您这个例子举的有点不适合。这里不能传递参数并不是继承的方法出现了问题。
而是在构建SUB的原型的时候,没有CALL Paretn。
我通过这样的写法,维持原来的继承方式不变,依然可以传递参数。
function Parent(n) {
this.name = n;
}
function Sub(n,a) {
Parent.call(this,n );
this.age = a;
}
Sub.prototype = new Parent();//设置继承
var a = new Sub("test",26);//没有办法在实例化时给name传递参数。
console.log( a.name )//控制台会输出test;
我认为对第三个缺点的解释通过下面的例子是比较合适的。
function Employee () {
this.name = "test";
this.dept = "general";
}
function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;
var amy = new WorkerBee;
Employee.prototype.name = "Unknown"
console.log( amy.name );//控制台输出test而不是"unknown"
第三个缺点是由于WorkerBee.prototype = new Employee;设置继承的时候出现的。
如果改成改成WorkerBee.prototype = Object.create( Employee.prototype );会出现另一种情况。
参数可以传递,但是amy这个实例里面没有name属性。
function Employee () {
this.name = "test";
this.dept = "general";
}
function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;
var amy = Object.create( Employee.prototype ) ;
console.log( amy.name );//控制台输出undefined
Employee.prototype.name = "Unknown"
console.log( amy.name )//控制台输出Unknown
因为在本地获得的是projects ,从__proto__中的WokderBee.prototype继承来的是Employee.prototype;而Employee.prototype并没有任何设置,所以amy并没有name这个属性,因为他没有从employee中继承到name。
至于第二个例子我可以这样理解吗??
a = new Sub(); a对象对象从本地中得到的是ID属性,offset属性是从__proto__继承来的。
a.__proto__ == Sub.prototype;
Sub.prototype = new Parent;
所以Sub.prototype 的本地中就存有offset属性。
a.offset.x = 200语句中,js首先会寻找a本地有没有offset属性,显然是没有的,所以他会到__proto__,也就是Sub.prototype里面寻找。而Sub.prototype本地中存放了offset属性。所以,如果a.offset.x = 200这样写,等于Sub.offset.x = 200,因此b 作为SUB的实例,b的值也会跟着改变。
请问,对于例子二我这样的理解正确吗??
对于例子一,我想我还需要消化一下。
function Employee () {
this.dept = "general";
}
Employee.prototype.name = "test";
function WorkerBee () {
Employee.call(this);
this.projects = [];
}
WorkerBee.prototype = Object.create( Employee.prototype );
var amy = new WorkerBee ;
console.log( amy.name );//控制台输出test
Employee.prototype.name = "Unknown"
console.log( amy.name )//控制台输出Unknown
amy.name = "foryou";
console.log(amy.name )//控制台输出FORYOU
[/quote]
呵呵,你有没有发现你这个例子与你主楼发的MDN上的例子是一样的。
对。这就是最完善的写法[/quote]
嗯嗯,谢谢大神的指点了,现在我已经更加理解JS的原型链和继承机制了。在我提的两个问题提中,通过跟您的讨论与自己的思考,我已经理解的比较多。关于第二个Constructor的问题,能不能跟第一个例子一样写几个例子来说说Constructor的一些实际应用和方法。
function Employee () {
this.dept = "general";
}
Employee.prototype.name = "test";
function WorkerBee () {
Employee.call(this);
this.projects = [];
}
WorkerBee.prototype = Object.create( Employee.prototype );
var amy = new WorkerBee ;
console.log( amy.name );//控制台输出test
Employee.prototype.name = "Unknown"
console.log( amy.name )//控制台输出Unknown
amy.name = "foryou";
console.log(amy.name )//控制台输出FORYOU
[/quote]
呵呵,你有没有发现你这个例子与你主楼发的MDN上的例子是一样的。
对。这就是最完善的写法
var arr = [];//想把每次创建的实例对象都自动放到arr数组中,好统一管理
function Parent() {
arr.push(this);
}
function Sub() {
this.name = "";
}
Sub.prototype = Object.create(Parent.prototype);//设置继承
alert(arr.length);//还没有创建实例对象,arr数组中就已经有一个了
var a = new Sub();
var b = new Sub();
alert(arr.length);//创建了两个实例对象,arr数组中还是只有一个
如果是这写的话,控制台输出的arr.length两次都是0。得不到我们想要的效果。[/quote]
用Sub.prototype = Object.create(Parent.prototype);//设置继承时就需要在Sub() 中使用 Parent.call(this); 与之配合[/quote]
我发现这样也是可以的。把Sub.prototype = Object.create( Parent.prototype );这局注释掉。加上CALL方法。就想下面这样写。在创建新的实例的时候也会将对象加入到ARR当中去。
var arr = [];//想把每次创建的实例对象都自动放到arr数组中,好统一管理
function Parent() {
arr.push(this);
}
function Sub() {
Parent.call(this);
this.name = "";
}
//Sub.prototype = Object.create(Parent.prototype);//设置继承
console.log(arr.length);//还没有创建实例对象,arr数组中就已经有一个了
var a = new Sub();
var b = new Sub();
console.log(arr.length);//创建了两个实例对象,arr数组中还是只有一个
//console.log( Parent.prototype );
console.log(arr);
我说说我的理解吧,不对的话请您指正。在SUB的构造函数里面调用PARENT的构造函数,使得SUB对象本地就有了这个语句 arr.push(this);,所以在实例化的时候,每实例化一次,就会有一个新的实例被PUSH进去ARR里面。
我觉得Sub.prototype = Object.create(Parent.prototype);这个语句并不起作用。
我试着输出了这个结果console.log( Sub.prototype );
这个语句返回的结果是:Parent{} ,说明了SUB从PARENT原型链上并没有继承得到任何的东西。
我增加了一个语句,Parent.prototype.test = "test";
然后输出console.log( Sub.prototype );输出结果是 Parent {test: "test"} ;
所以,我认为在不设置Parent.prototype 的情况下,我们写Sub.prototype = Object.create( Parent.prototype ),是没有意义的,因为SUB从原型链上继承不了任何东西。
真正起作用的是CALL语句。
[/quote]
不写Sub.prototype = Object.create( Parent.prototype ),
对象实例a 就不属于 Parent类的了;
console.log(a instanceof Parent);
function Employee () {
this.dept = "general";
}
Employee.prototype.name = "test";
function WorkerBee () {
Employee.call(this);
this.projects = [];
}
WorkerBee.prototype = Object.create( Employee.prototype );
var amy = new WorkerBee ;
console.log( amy.name );//控制台输出test
Employee.prototype.name = "Unknown"
console.log( amy.name )//控制台输出Unknown
amy.name = "foryou";
console.log(amy.name )//控制台输出FORYOU
var arr = [];//想把每次创建的实例对象都自动放到arr数组中,好统一管理
function Parent() {
arr.push(this);
}
function Sub() {
this.name = "";
}
Sub.prototype = Object.create(Parent.prototype);//设置继承
alert(arr.length);//还没有创建实例对象,arr数组中就已经有一个了
var a = new Sub();
var b = new Sub();
alert(arr.length);//创建了两个实例对象,arr数组中还是只有一个
如果是这写的话,控制台输出的arr.length两次都是0。得不到我们想要的效果。[/quote]
用Sub.prototype = Object.create(Parent.prototype);//设置继承时就需要在Sub() 中使用 Parent.call(this); 与之配合[/quote]
我发现这样也是可以的。把Sub.prototype = Object.create( Parent.prototype );这局注释掉。加上CALL方法。就想下面这样写。在创建新的实例的时候也会将对象加入到ARR当中去。
var arr = [];//想把每次创建的实例对象都自动放到arr数组中,好统一管理
function Parent() {
arr.push(this);
}
function Sub() {
Parent.call(this);
this.name = "";
}
//Sub.prototype = Object.create(Parent.prototype);//设置继承
console.log(arr.length);//还没有创建实例对象,arr数组中就已经有一个了
var a = new Sub();
var b = new Sub();
console.log(arr.length);//创建了两个实例对象,arr数组中还是只有一个
//console.log( Parent.prototype );
console.log(arr);
我说说我的理解吧,不对的话请您指正。在SUB的构造函数里面调用PARENT的构造函数,使得SUB对象本地就有了这个语句 arr.push(this);,所以在实例化的时候,每实例化一次,就会有一个新的实例被PUSH进去ARR里面。
我觉得Sub.prototype = Object.create(Parent.prototype);这个语句并不起作用。
我试着输出了这个结果console.log( Sub.prototype );
这个语句返回的结果是:Parent{} ,说明了SUB从PARENT原型链上并没有继承得到任何的东西。
我增加了一个语句,Parent.prototype.test = "test";
然后输出console.log( Sub.prototype );输出结果是 Parent {test: "test"} ;
所以,我认为在不设置Parent.prototype 的情况下,我们写Sub.prototype = Object.create( Parent.prototype ),是没有意义的,因为SUB从原型链上继承不了任何东西。
真正起作用的是CALL语句。
var arr = [];//想把每次创建的实例对象都自动放到arr数组中,好统一管理
function Parent() {
arr.push(this);
}
function Sub() {
this.name = "";
}
Sub.prototype = Object.create(Parent.prototype);//设置继承
alert(arr.length);//还没有创建实例对象,arr数组中就已经有一个了
var a = new Sub();
var b = new Sub();
alert(arr.length);//创建了两个实例对象,arr数组中还是只有一个
如果是这写的话,控制台输出的arr.length两次都是0。得不到我们想要的效果。[/quote]
用Sub.prototype = Object.create(Parent.prototype);//设置继承时就需要在Sub() 中使用 Parent.call(this); 与之配合
var arr = [];//想把每次创建的实例对象都自动放到arr数组中,好统一管理
function Parent() {
arr.push(this);
}
function Sub() {
this.name = "";
}
Sub.prototype = Object.create(Parent.prototype);//设置继承
alert(arr.length);//还没有创建实例对象,arr数组中就已经有一个了
var a = new Sub();
var b = new Sub();
alert(arr.length);//创建了两个实例对象,arr数组中还是只有一个
如果是这写的话,控制台输出的arr.length两次都是0。得不到我们想要的效果。