js面向对象编程
①:字面量方式创建。
其实就是json形式的对象,适用于创建单个对象。
例:var obj = {
name:"小明",
age:18,
run: function(){
console.log(this.name)
}
}
②:实例创建。
实例创建对象,使用new Object()创建一个实例对象,然后再给这个对象添加属性和方法。
例:var box = new Object(); //创建一个Object对象
box.name = "小明"; //创建一个name属性并赋值
box.age= 18; //创建一个age属性并赋值
box.run = function(){ //创建一个run ()方法并返回值
console.log(this);
return this.name + '--' + this.age
}
缺点:想创建一个类似的对象,就会产生大量的代码。
例:var box2 = box //得到box的引用
box2.name = "小明"; //直接改变了name属性
console.log(box2.run());
console.log(box.run()); //box的name也改变了
var box2 = new Object(); //创建一个Object对象
box2.name = "小红";
box2.age= 20;
box.run = function(){
console.log(this);
return this.name + '--' + this.age
}
console.log(box2.run()) //这样才避免和box混淆,从而保持独立
③:工厂模式创建对象
解决实例化对象产生大量重复代码的问题;工厂模式创建对象,其实就是函数封装
例:function createObject(name,age){ //集中实例化函数
var obj = new Object(); //原材料
obj.name = name; //加工
obj.age = age;
obj.run = function(){
return this.name + '--' + this.age;
};
return obj; //出厂
}
var box1 = createObject('Lee' , 100); //第一个实例
var box2 = createObject('Jack , 200); //第二个实例
console.log(box1.run())
console.log(box2.run()) //保持独立
工厂模式解决了重复实例化的问题,但是还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。
例:console.log(typeod box1); //Object判断对象类型。
//instanceof运算符,一个对象是否为指定的构造函数的实例,返回布尔值
console.log(box1 instanceof Object); //true box1是Object1的实例
console.log(box1 instanceof createObject); //false
但是我们box1应该是createObject创建出来的。
④:构造函数创建对象
构造函数创建对象,是使用最多的创建对象的方式,也是将所有的操作都封装在函数中,但是跟工厂模式的创建方式有很大的不同,而且可以明确区分对象的种类。
构造函数的特点:
∝:构造函数名首字母大写(为了区分普通函数,不是必须,是约定)
∝:构造函数方法没有显示的创建对象(new Object())
∝:直接将属性和方法赋值给 this 对象
∝:没有 return 语句,不需要返回对象
∝:通过构造函数创建对象,必须使用 new 运算符(直接调用跟普通函数一样)
例:function Student(namne){ //首字母大写
this.name = name; //不用new Object,直接通过this添加属性和方法
this.eat = function(){
console.log("吃饭")
}
}
//实例对象
var s1 = new Student('MM'); //必须使用new
var s2 = new Student('GG);
console.log(s1 instanceof Student); //true , s1是Student创建出来的
要创建 Student 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下4个步骤:
(1)创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3)执行构造函数中的代码(为这个新对象添加属性);
(4)返回新对象。
缺点:console.log(s1.eat == s2.eat); //false,判断内存地址
同一个方法,因对象不同,所存储的位置也不同,如果有多个对象,则要分配存储多次,占用不必要内存。
⑤:原型创建对象
1)原型prototype
每个对象都会有自己的原型对象,是这类对象共有的方法和属性的集合。如Array 对象的原型对象中定义了很多的方法和属性,所有的数组都能使用这些方法和属性。
例:var arr = [1]

通过原型创建的对象,对象的方法和属性是共享的,只会存储一次,因此能够解决内存浪费的问题。但是会出现一个新的问题,原型创建的对象的属性不能传参,都是固定的值。这样的话就不能创建不同的对象了。
无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针
⑥:混合模式创建(构造 + 原型)
用构造函数创建对象,会有重复定义方法的问题,用原型创建属性不能传参,所以这里结合一下,用构造函数 + 原型 混合使用的方法创建对象,构造函数中放属性和一直改变的方法,原型中存储共享的属性和方法。
例:
上面代码中,通过混合创建的方式,在构造函数中放一些可变的属性和方法,通过参数传入,在原型对象中,
添加共享的不变的属性和方法,节约内存。但是也会有人说,创建对象分成了两部分,破坏了对象的封装性的特点
⑦:动态混合模式。
一般创建对象用混合模式就够了,但是严格来说这种方式破坏了封装性,所以还可以使用动态混合模式创建,将原型方法也写到构造函数当中
例:

浙公网安备 33010602011771号