js 是更倾向于函数式编程了还是更倾向于面向对象?或者没有倾向?只是简单的提供了更多的语法糖?

作为一个入门级js学习者,是否应该主动向函数式变成靠拢?还是应该保持js一切皆对象的特性,使用面向对象的编程方式来进行日常coding; 以后的发展方…
关注者
96
被浏览
17,172
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

很多大大,都说的是没有倾向,我想在这里表达一些不同角度的看法。


如果是对于涉及到 “继承” 方面的代码来说,还有一种是委托设计,也就是对象关联风格。这种风格 相较于面向对象风格来说更加接近于 javascript 的 “继承”机制。

原因有下:

1、javascript 其实并没有类的概念;

2、在继承和实例化的过程中,javascript的对象机制并不会自动执行复制行为。简单来说,javascript中只有对象,并不存在可以被实例化的“类”。一个对象并不会被复制到其它对象,他们只会被关联起来,也就是复制的是其实是引用。而对于其他传统语言来说,继承实际上是复制;

两张图 表示继承。

传统语言实现继承 ,箭头表示复制操作


javascript 实现继承,箭头表示 关联,也就是 引用。


面向对象 这种风格就是我们利用 javascript 函数的一种特殊特性:所有的函数默认都会有一个名为 prototype 的公有并且不可枚举的属性,它会指向另一个对象 这一点来模拟出了类似于其它传统语言实现继承的方式。

但是说是 继承 其实是不准确的,因为传统面向类的语言中 继承 意味着复制操作,而 javascript (默认)并不会复制对象属性,而是在两个对象之间创建一个关联,这样一个对象可以 委托 访问另一个对象的属性和函数。委托 可以更加准确的描述javascript中对象的关联机制。


面向对象的类式风格的继承:

function Foo(who){
    this.me = who;
}

Foo.prototype.identify = function(){
    return "i am “ + this.me;
}

function Bar(who){
    Foo.call(this,who);
}

Bar.prototype = object.create(Foo.prototype);

Bar.prototype.speak = function(){
    alert(“Hello,”+ this.identify()+”.”);
}

var b1 = new Bar(“b1”);
var b2 = new Bar(“b2”);

b1.speak();
b2.speak();

子类 Bar 继承了 父类 Foo,然后生成了 b1 和 b2 两个实例。 b1 继承了 Bar. prototype , Bar.prototype 继承了 Foo.prototype。


委托设计风格,也就是对象关联风格:

Foo = {
    init:function(who){
        this.me = who;  
    },
    identify:function(){
        return “i am” +this.me;
    }
};

Bar = Object.create(Foo);
Bar.speak = function(){
    alert(“hello,” + this.identify())
};

var b1 = Object.create(Bar);
b1.init(“b1”);
var b2 = Object.create(Bar);
b2.init(“b2”);

b1.speak();
b2.speak();

这段代码同样 利用 [[prototype]] 把 b1 委托给 Bar 并把 Bar 委托给 Foo,和上一段代码一摸一样,同样实现了三个对象的关联。


委托设计模式不是按照父类到子类的关系垂直组织的,而是通过任意方向的委托关联并排组织的。

其次,代码实现明显不同,可以感觉到 委托设计模式,也就是对象关联风格更加简洁,这种设计模式只关注对象之间的关联关系。 最后,委托设计模式更加贴近 javascript 的 “继承”机制 —— 委托机制。


所以说,确实没有倾向,你可以用任何风格来写,甚至不同风格的混搭,但是在实现某些功能的时候,应该还是会有最优解,也就是在某种程度上是有倾向的。以上就是一个例子:站在 继承 角度来说 委托关联 要好于 面向对象。


函数式编程也是很火的编程方式,有很多函数式编程的库,像underscore。它主要不同于其它的区别是设计的函数方法并不会属于任何一个对象,对象只是 这些函数方法的参数。而像面向对象的编程(oop)风格则是 设计的函数方法都隶属于一个对象。作为对象的一个属性。

例子:

函数式编程

 var arr = [1, 2, 3];
 _.map(arr,function(item) {
      return item * 2;
 });

面向对象:

 var arr = [1, 2, 3];
 arr.map(function(item) {
      return item * 2;
 });

函数式编程风格的有点就是在于对于 状态的管理。尽量减少可见的状态修改,将尽可能的变化抽象压缩到最小区域去。


所以没有哪个好哪个不好,只有针对不同功能实现,不同需求的最优解,都有优点,你需要做的是找到 将优点发挥到极致,同时尽量减少缺点的危害的实现方式。



我好像跑题了。。。。

轻喷。



上面关于继承的写的比较简略,详细可以看我的专栏里,有片长文,以助催眠。

【 js 基础 】Javascript “继承”