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),这四个数据属性也是对象属性的默认四个数据属性:
- configurable:表示能否使用delete操作符删除从而重新定义,或能否修改为访问器属性。默认为true;
- Enumberable: 表示是否可通过for-in循环返回属性。默认true;
- Writable: 表示是否可修改属性的值。默认true;
- Value: 包含该属性的数据值。读取/写入都是该值
正如我写obj的name属性configurable: false,writable: false,
后
obj.name = "wscats";//无效
delete obj.name;//无效
删除该对象的name属性值和修改name属性值也变得无效
共同学习,写下你的评论
评论加载中...
作者其他优质文章