Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript面向对象之一(封装) #19

Open
Pomelo1213 opened this issue Apr 12, 2018 · 0 comments
Open

JavaScript面向对象之一(封装) #19

Pomelo1213 opened this issue Apr 12, 2018 · 0 comments
Labels
JavaScript JavaScript

Comments

@Pomelo1213
Copy link
Owner

写在前面


首先这篇文章是来自阮一峰大佬的2010年的博客!!!![戳这里] 👍 (http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html)

我2010的时候还在谈恋爱(逃)

自己在学习到面向对象这里有些疑惑,越学越糊涂,可能是Java的副影响。。 : -(

打算重头梳理一下,然后看了这篇博客,觉得读完了应该自己输出一遍才能是自己的。


在JavaScript里面对象是很常见,在这里函数也成为函数对象。但是这里对象又不是真正的对象,它的语法中没有Class(不涉及ES6的话),那么封装成对象应该怎么去做呢?,下面就来具体说说:

1.原始模式


我们有两只猫,它有自己的颜色和名字:

var cat1 = {
    name: 'po',
    color: 'orange'
}

var cat2 = {
    name: 'da',
    color: 'white'
}

缺点很明显,如果咱有上千只猫,那我们就要累死了。所以就需要进行改进。

2.原始模式改进


function Cat(name, color){
    return {
        'name': name,
        'color': color
    }
}

var cat1 = Cat('po', 'orange')
var cat2 = Cat('da', 'white')

这样是不是就好看了许多,但是缺点是cat1和cat2没有实质关联,两者纯粹是函数调用。这样跟我们的面向对象一点都不像。

3.构造函数模式


由于以上的缺点就出现了构造函数的形式,如下:

function Cat(name, color){
    this.name = name
    this.color = color
}

var cat1 = new Cat('po', 'orange')
var cat2 = new Cat('da', 'white')
alert(cat1.name) //po
alert(cat2.name) //da

这样一来就可以将cat1和cat2创造了关联,还使用了new来进行实例化。

💣这时cat1和cat2会自动含有一个constructor属性,指向它们的构造函数。

console.log(cat1.constructor === Cat) //true
console.log(cat2.constructor === Cat) //true

上面这段话是大佬原文中的话,但是我觉得这段话造成了误导。所以重新说一下。上面两段代码为true,没错。但是!!在cat1和cat2本身上是没有constructor属性,而是会去Cat.prototype上面去找,所以准确的来说应该是这样的

console.log(Cat.prototype === Cat) //true

这里顺带提一下new做了哪些事

var temp = {}
temp.__proto__ = Cat.prototype
Cat.call(temp)
return temp

看了new做的第二件事,就应该理解了为什么cat1和cat2本身没有constructor。

构造函数模式问题


这么好的方法实现,为什么还要改进呢?

//如果我需要添加一个eat该怎么写呢?
function Cat(name, color){
    this.name = name
    this.color = color
    this.eat = function(){ console.log('eaaaaaaaaaaaaat') }
}

var cat1 = new Cat('po', 'orange')
var cat2 = new Cat('da', 'white')
console.log(cat1.eat) //eaaaaaaaaaaaaat
console.log(cat2.eat) //eaaaaaaaaaaaaat
console.log(cat1.eat === cat2.eat) //false

看上面,确实是实现了eat的方法,但是这个方法对应的不是同一块内存,这是为什么呢?因为我们new干了这件坏事,new中每次都是创建了一个空对象。

Prototype模式


怎么改进上面的问题呢?

Cat.prototype.eat = function(){ console.log('eaaaaaaaaaaaaat') }
cat1.eat() //eaaaaaaaaaaaaat
cat2.eat() //eaaaaaaaaaaaaat
console.log(cat1.eat === cat2.eat) //true

对,直接在构造函数的原型上面去找eat方法就可以。儿子没有方法去父亲身上找,这不就有点像面向对象了吗?

未完。。。

@Pomelo1213 Pomelo1213 added the JavaScript JavaScript label Aug 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JavaScript JavaScript
Projects
None yet
Development

No branches or pull requests

1 participant