《JavaScript高级程序设计》中的一个疑点
发布于 5 年前 作者 JarvisQJ 3591 次浏览 来自 问答

在看《JavaScript高级程序设计》,章节6.2.2中最后(147页)提供了一种构造函数定义方式,但作者自己又说有问题,但并未讲清楚问题是什么,所以请大家讲讲?

function Person(name, age, job){
 this.name = name;
 this.age = age;
 this.job = job;
 this.sayName = sayName;
}
function sayName(){
 alert(this.name);
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.sayName===person2.sayName; // true

这段代码的原文评注如下: 在这个例子中,我们把sayName()函数的定义转移到了构造函数外部。而在构造函数内部,我们 将sayName 属性设置成等于全局的sayName 函数。这样一来,由于sayName 包含的是一个指向函数 的指针,因此person1 和person2 对象就共享了在全局作用域中定义的同一个sayName()函数。这 样做确实解决了两个函数做同一件事的问题,可是新问题又来了:在全局作用域中定义的函数实际上只 能被某个对象调用,这让全局作用域有点名不副实。而更让人无法接受的是:如果对象需要定义很多方 法,那么就要定义很多个全局函数,于是我们这个自定义的引用类型就丝毫没有封装性可言了。

有木有觉得粗体这段不知所云?

6 回复

在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域有点名不副实。

说的是sayName函数是在全句作用域创建,但实际只被Person引用,所以全局作用域有点名不副实

如果对象需要定义很多方法,那么就要定义很多个全局函数,于是我们这个自定义的引用类型就丝毫没有封装性可言了。

定义多个全局函数,既然是全局的,其实就没有封装可言了

所以可以将sayName挂载到Person原型上

function Person(name, age, job){
 this.name = name;
 this.age = age;
 this.job = job;
}
Person.prototype.sayName = function(){
 alert(this.name);
}

这样即做到了封装性,又不会在示例化Person时重复赋值方法

这很明显是作者词不达意。他自己脑海中有这段文字的上下文环境,但他就是不用文字表述出来。算不上“明师”。我们读文献遇到的迷惑的地方,大部分是由于这种语焉不详的描述导致的。

@masongzhi

说的是sayName函数是在全句作用域创建,但实际只被Person引用,所以全局作用域有点名不副实

function Person(name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = sayName;
}
function Animal(name, age) {
  this.name = name;
  this.age = age;
  this.sayName = sayName;
}
function sayName() {
  alert(this.name);
}
const person1 = new Person('Nicholas', 29, 'Software Engineer');
const cat = new Animal('Kitty', 2);
person1.sayName(); //Nicholas
cat.sayName(); //Kitty

原作者的字面意思貌似是你说的这样,但是这个说不通啊

定义多个全局函数,既然是全局的,其实就没有封装可言了

如果把这段代码放在一个单独的文件,不就有封装性了吗,而实际我们也就这么做啊。

@JarvisQJ 放到单独的文件是模块化带来的封装性(比如ES模块中单独的文件如果没有import和export,那么文件中的变量都被视为全局变量),‘“于是我们这个自定义的引用类型就丝毫没有封装性可言了”,这句话更多强调了对于Person类的封装性,两者区别还是很大的,sayname方法明显是Person的专属方法,但是现在这样子,我们可以导入这个文件,在无需创建Person类的实例即可调用到sayname方法,你可以看看Java,都是把方法写到类里面,要不通过实例调用,要不通过类名.method 调用静态方法 ,

这段粗体描述的有什么问题吗, 封装的概念是不想让不该访问的目标访问到, 从而提高单元的内聚性, 提高内聚性可以进一步提高程序的可维护性, 因为它尽量让功能保持单一, 维护的时候成本会被降低. 题主理解的封装性只局限于文件范围的封装性, 可能有点偏差, 学软件工程的飘过…

@TianQiDing 你说的都对,但是能不能更加具体点解释一下粗体字的意思

回到顶部