为了账号安全,请及时绑定邮箱和手机立即绑定

Javascript面向对象编程

JS面向对象的程序设计,JS在很早以前一直被认为毫无章法的语言,大部分初学者写的时候都是运用面向过程的思维来编写JS的(一页下来就是一个function接着另一个function的写法)

其实JS中function就是一个对象,如下面的代码

var HelloWscats = function(){
    console.log("wscats is not cat");
}

var _init = function(){
    var obj = new HelloWscats();
}

_init();//log:wscats is not cat

此时我们就可以调用_init 方法后打印wscats is not cat,它调用了HelloWscats的对象,当然这个HelloWscats对象没有任何属性和方法,它只有一个构造方法HelloWscats(),相当于调用了一个没有任何属性的方法和的类,当使用new进行创建的时候,就调用了它的构造方法(也就是执行了HelloWscats里面的console.log("wscats is not cat");),当然现在很多JS的对象直接是定义了属性而已,而构造方法里面是没有其他可执行的代码的

其实HelloWscats 就是我们所说的创建对象中的其中一种构造函数模式

var _init2 = function(param){
    var obj = new Object();
    var obj = {}
    obj.action = "b";
    Object.defineProperty(obj, "name", {
        configurable: false,
        writable: false,
        value: "Wscats",
    });
    obj.name = "wscats";//无效
    delete obj.name;//无效
    console.log("wscats is not cat");
    return obj;
}
_init2("wscats is not cat");

我们稍微改一下,执行_init2函数的时候,相当于创建对象中的另一种我们说的工厂模式,创建对象交给一个工厂方法(_init2)来实现,可以传递参数,这里创建对象的方式跟构造函数方式的区别在于
构造函数能看到具体的定义对象类型HelloWscats,而工厂模式不能,因为工厂模式创建对象都是使用Object的原生构造函数来完成的,如图
本质是这两句结果的区别

var obj = new HelloWscats();//构造HelloWscats函数,并实例化HelloWscats对象
var obj = new Object();//new一个Object对象,在工厂函数里面扩展该对象,并return该对象

再写一个简单的例子来说明他们的区别,如下

var Constructor = function() {
    console.log("wscats is not cat from constructor");
}

var objFromConstructor = new Constructor();

var Factory = function() {
    var obj = new Object();
    console.log("wscats is not cat from factory");
    return obj;
}

var objFromFactory = Factory();

上面就是一个最简单的对象,不过既然是对象,肯定是要赋予它属性和方法的
我们可以用prototype这个原型的关键字进行赋值,比如我们要给HelloWscats对象增加一个name属性和say方法,那我们就可以这样添加

var HelloWscats = function(){
    this.action = "Code";
    console.log("wscats is not cat");
}

HelloWscats.prototype = {
    name: "wscats",
    say: function(){
        console.log("Wscats is not cat");
    }
}

HelloWscats.prototype.skill = "Good Cat";

var _init = function(){
    var obj = new HelloWscats();
    obj.say();
    console.log(obj);
}

_init();

这里我们看到了先是执行了构造函数中的console.log("wscats is not cat");,然后在执行原型链中的console.log("Wscats is not cat");
打开浏览器看看打印的obj对象具体是怎么样的

上面有一定注意的是,如果我实例化了HelloWscats对象

var _init = function(){
    var obj = new HelloWscats();
    obj.say();
    obj.action = "b";
    console.log(obj);
}

我们可以改变,这个对象的action属性obj.action = "b";,但我们没办法改变原型链的对象,这个就类似于继承了HelloWscats对象的原型链的对象,继承的这些子类无法更改,但是子类可以修改自己本身的属性和方法

var HelloWscats = function(){
    var privateVvariables = "I am ur cat";
    this.getPrivate = function(){
        console.log(privateVvariables);
    }
    this.action = "Code";
    console.log("wscats is not cat");
}

HelloWscats.prototype = {
    name: "wscats",
    say: function(){
        console.log("Wscats is not cat");
    }
}

HelloWscats.prototype.skill = "Good Cat";

var _init = function(){
    var obj = new HelloWscats();
    obj.say();
    obj.action = "b";
    obj.getPrivate();
    console.log(obj);
}

_init();

下面我可以继续在构造函数里面写一个var privateVvariables = "I am ur cat";来让HelloWscats拥有一个私有成员变量,当然这个变量也只有该对象的方法能访问,具体就是this.getPrivate函数能读到该私有变量的成员

this.getPrivate = function(){
    console.log(privateVvariables);
}

它的巧妙之处其实在于这个构造函数的作用域,只能在类的构造函数里面进行访问该私有变量

var _init = function() {
    var obj = new HelloWscats();
    obj.say();
    obj.action = "b";
    obj.getPrivate();
    Object.defineProperty(obj, "name", {
        configurable: false,
        writable: false,
        value: "Wscats",
    });
    obj.name = "wscats";//无效
    delete obj.name;//无效
    console.log(obj);
}

上面我们一直用obj.name = "wscats"或者obj = {name: "wscats"}这两种方法来编辑或者定义obj的属性,那么有没有其他更好的方法呢,答案是有的,正如上面的这一段代码

Object.defineProperty(obj, "name", {
    configurable: false,
    writable: false,
    value: "Wscats",
});

defineProperty方法能修改对象的属性它接收三个参数:属性所在对象,属性名和一个描述符对象(必须是:configurable、enumberable、writable和value,可设置一个或多个值)
他可以设置以下的数据属性(他们默认都为true),这四个数据属性也是对象属性的默认四个数据属性:

  1. configurable:表示能否使用delete操作符删除从而重新定义,或能否修改为访问器属性。默认为true;
  2. Enumberable: 表示是否可通过for-in循环返回属性。默认true;
  3. Writable: 表示是否可修改属性的值。默认true;
  4. Value: 包含该属性的数据值。读取/写入都是该值

正如我写obj的name属性configurable: false,writable: false,

obj.name = "wscats";//无效
delete obj.name;//无效

删除该对象的name属性值和修改name属性值也变得无效

点击查看更多内容
7人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消