各位好,关于类方法的定义有点疑惑,下面是两种方法给Person类定义方法sayHello(),输出结果是一样,但是两者的结构不一样,这两者结构有什么区别呢
function Person(firstName) {
this.firstName = firstName;
}
Person.prototype.sayHello = function() {
};
var person1 = new Person("Alice");
var person2 = new Person("Bob");
// call the Person sayHello method.
person1.sayHello(); // alerts "Hello, I'm Alice"
person2.sayHello(); // alerts "Hello, I'm Bob"
function Person(firstName) {
this.firstName = firstName;
this.sayHello = function() {
};
}
var person1 = new Person("Alice");
var person2 = new Person("Bob");
// call the Person sayHello method.
person1.sayHello(); // alerts "Hello, I'm Alice"
person2.sayHello(); // alerts "Hello, I'm Bob"
天蓬老师2017-04-10 15:18:40
第一种
sayHello方法定义在Person的prototype中,如果有另一类SuperMan继承之Person,那么新SuperMan将会继承sayHello方法
第二种
sayHello只属于Person这个类,如果有另一类SuperMan继承之Person,那么新SuperMan将不会有sayHello方法
大家讲道理2017-04-10 15:18:40
第一个例子:
person1.hasOwnProperty('sayHello')
//false
第二个例子
person1.hasOwnProperty('sayHello')
//true
懂了咩?第一个是在原型中定义的sayHello
方法,所以调用的时候是在原型链中调用的。
第二个在使用new操作符生成实例的时候,将sayHello
方法定义到了实例中,所以调用的是自身的方法。
伊谢尔伦2017-04-10 15:18:40
输出结果是一样,但通常使用第一种写法。
首先对于属性而言,每个实例都可能会有不同,比如你的例子中每个人有不同的名字,但对于方法而言,一般来说每个实例都是相同的,比如你的例子中是输出自己的名字,所以没有必要在每个实例中都添加相同的方法,而是利用原型进行共享。
为什么可以利用原型共享?在进行属性的GET时(Property resolving),如果自有属性中找不到,就去对象的原型中找,依次类推。利用这一特点,达到共享的目的。
天蓬老师2017-04-10 15:18:40
这两种方式区别的在于:
1、你的“逻辑”是需要实例共享的还是需要各自维护的。
2、你的“逻辑”是实例在编码阶段就确定(静态逻辑)还是在编码阶段之外才确定(动态逻辑)。
当你需要在动态执行期改变某个实例的“逻辑”,而非所有实例的“逻辑”,类似继承的概念,这个时候第二种方式才可以实现。
例如:
function A() {
this.f = function(){//默认行为}
}
Person.prototype.changeF = function(func){this.f = func}
a1 = new A();
a2 = new A();
a3 = new A();
a3.changeF(function(){//非默认行为});
//a1.f == a2.f;
//a1.f != a3.f;
ps:一般插件都采用这种方式,即我确定一种方式,然后我还提供你可以在不改变我任何逻辑的前提下,任意插接你的新逻辑进来
PSS:插入一个图片
迷茫2017-04-10 15:18:40
简单的说:
第一种是new出来的person实例本身是没有sayHello的方法,它在自身没有该方法的时候,会顺着原型链找这个方法,在原型链找到了就会使用,没有就返回undefined
第二种是new出来的实例本身就有这个sayHello方法,因为这个方法在构造函数就挂在了this身上,不过这种相对于第一种会占用更多内存
你需要了解下面向对象的构成还有原型链这些东西
建议看下阮一峰的文章-Javascript的面向对象编程
我说的可能不是很好理解,还是看大神的文章把