JavaScript之----面向对象和原型

时间:2022-05-12 19:47:41
ECMAScript有两种开发模式:1、函数式(过程化),面向对象(oop)【好处:有了引用类型的对象可直接调用这个对象对应的方法】 任何一个事物都可以看成是一个对象 1、创建对象 var stu1 = new Object();   //小丽 等于 新 老婆(); stu1.name="小丽";//属性name就是一个变量 stu1.study =function(){         alert("我叫"+this.name+"爱学习"); };    //实现学习这个功能,行为 定义为函数 alert.name; alert.study();
这种方式创建了多个学生对象,重复性代码很多
2、使用工厂模式创建对象:解决实例化对象产生大量重复的问题(属性和行为时一样的) function createObj(name,age){     var obj = new Object();     obj.names =name;     obj.ages = age;     obj.study = function(){                      alert("我叫"+this.names+"今年"+this.ages+"爱学习");            }; return obj;//返回的是对象的引用 } var stu3 =createObj("张三",23);//var stu3 = obj; //解释一下子: return obj    最后把obj这个对象返回了,返回的是个引用(var obj = new Object();),stu3接收到了obj这个引用,引用里存放的是new Object()这个对象的内存地址,所以stu3接收到的是这个对象的地址,stu3也就指向了张三这个对象

var stu4 =createObj("李四",22);
工厂模式存在的问题:不能确定对象具体的类型

3、使用构造函数(方法)创建特定的对象:
//根据创建对象来起名字
function Student (name,age){         this.name = name;    //后台自动创建了 new Object()         this.age = age;           //this就指向了这个对象         this.study=function(){                         alert(this.name+","+this.age);             };                                   //后台返回了该对象      } var stu1 = new Student("zhang",23); alert(stu1.name); alert(stu1.age); stu1.study(); var stu2 = new Student("李斯",20);alert(stu2.name);alert(stu2.age);stu2.study();


//注意:构造函数和工厂模式的区别:             1、构造函数中直接给name、age赋值,没有显示的创建对象(new object());              2、直接将属性和方法赋值给this对象;              3、没有使用return返回;
构造函数的特点: (1)、定义构造函数是 构造函数的函数名首字母大写,为了和普通函数区分 (2)、使用构造函数时必须使用new(这样才能生成一个新的对象例如:var stu1 = new Student("zhang",23);     把构造函数当成普通函数调用:Student(“张三”,40);没有任何意义(X)因为这个函数没有返回值,得不到对象,只有new之后,后台才能返回对象。 (3)、alert(stu1 instanceof Student);  //判断stu1具体什么类型的实力,判断stu1是不是Student这种类型的,显示true 或 flase (4)、构造函数中的函数study 是一个引用类型变量 存放的是函数的地址(函数的引用)每new一个对象中的函数study的地址是不同的
4、使用原型 原型的好处:实现了数据的共享。 引用类型中都含有prototype(原型)属性,该属性指向对象 var obj = {         country:"中国"; };//定义一个对象,给对象定义一个country属性值为中国
function Student (name,age){        this.name = name;           this.age = age;           this.study=function(){                        alert(this.name+","+this.age);            };                               }
Student.prototype =obj;//把Student的原型设置为obj对象(把Student引用类型的这种函数的prototype属性指向obj这个对象 var stu1 = new Student("zhang",23);var stu2 = new Student("li",20); alert(stu1.country);//显示中国 alert(stu2.country);//显示中国

注意:是给创建对象的这个构造函数定义原型,从而使用Student创建的对象中都具备了原型对象obj中的这个内容。
prototype写成 _ _proto_ _ JavaScript之----面向对象和原型
如果是一个对象,看他的原型对象:obj.__proto__(用__proto__)
stu1._ _proto_ _  得到stu1的原型对象
stu1._ _proto_ _._ _proto_ _  得到的是obj的原型对象 obj._ _proto_ _     得到的是obj的原型对象
显示的也是一个object类型的一个对象 obj._ _proto_ _ ._ _proto_ _  //显示的是空   最基本的object类型中就没有原型对象了   得到的是obj的原型对象的原型对象


//判断一个对象是否指向了构造函数的原型对象 alert(Student.prototype.isPrototypeOf(stu1));//返回的是true 或是flase 解释一下:判断stu1是不是指向了构造函数Student的原型对象  比较谁isPrototypeOf(***)  ***就写谁
stu1.name  指的是stu1对象中的属性name值 如果原型对象中也有个name var obj = {        country:"中国";        name:"tom";};stu1.name 还是指的是stu1对象中的属性name值
说明:对象中含有name属性则优先使用对象中的属性,如果对象中没有的属性再到原型中查找有没有需要的属性    (构造方法中自己有的属性就用自己的,没有的再用原型中的)
①hasOwnProperty()方法:判断是否自己含有的属性
alert(stu1.hasOwnProperty('name'));  //显示true   对象stu1中本身就有name属性
②'name' in stu1 这种方法是看一下stu1中(无论是自身还是原型中)是否含有name属性
Student中如果不设置prototype属性的值,他也含有默认的object对象(Student本身就含有prototype原型对象)
Student.prototype =obj;覆盖了Student的原有的原型对象
obj的原型对象是object JavaScript之----面向对象和原型
obj具备object里面的属性和方法
Student具备obj里面的属性和方法也具备object里面的属性和方法
默认原型和设置的原型的区别: var stu =  new Student("zhang",22); 构造 constructor属性   stu .constructor表示stu这个对象的构造方法是什么
如果使用的是默认原型object时 stu .constructor使用的构造函数是 function Student(name,age){} 如果使用的是obj这个原型时 stu .constructor使用的构造函数是obj 的构造方法 就是 functionObject(){}这个构造方法
如果我们用的是Student.prototype = obj;这个原型时,但是我们想用的是Student这个构造方法所以在原型对象要这样写: var obj ={         constructor:Student,                    //要加上这句,意思是强制创建的stu对象时使用的构造方法为Student方法         country:"中国"     }; 或者不覆盖原型,向原型对象中添加一个新属性(在Student原有的原型对象中添加一个country属性,使用的是本来的默认原型对象) Student.prototype.country = "中国"   这两种方式,建议使用第一种方式

function Student (){ }Student.prototype = {        name:"xin",        age:22,        family:['妈妈','爸爸'],        fun:function(){                    return this.name;                }};这样是有问题的, 创建的任何一个对象的姓名和年龄都相同了,对于引用类型放到原型中,若一个对象进行其修改,其他对象都变化了。(对特有的属性应定义在构造函数中,而共享的定义在原型当中  解决这个问题利用构造函数+原型  这种模式      如下:
5、使用构造函数+原型 function Student (name,age){           //每个对象特有的数据使用构造函数         this.name = name;           this.age = age;           this.family =['妈妈','爸爸'];                                }
Student.prototype = {            //所有对象共享的内容定义在原型对象中     fun:function(){             return this.name + this.age+ this.family;     } }
var stu1 = new Student("liso",20); stu1.family.push("姐姐");//给stu1的family中添个姐姐 alert(stu1.family);//显示的是 妈妈 爸爸 姐姐 var stu2 = new Student("zhao",21); alert(stu2.family);//显示的是  妈妈 爸爸 这样就互不影响了
6、使用动态原型
动态原型模式:将两部分写在一起
function Student (name,age){              this.name = name;           this.age = age;           this.family =['妈妈','爸爸'];    
//原型直接写在构造函数当中              alert("原型被初始化开始");Student.prototype.fun = function(){            return this.name + this.age+ this.family;    }    alert("原型被初始化结束");
 }
var stu1 = new Student("liso",20);alert(stu1.fun());//显示liso,20,妈妈 爸爸
var stu2 = new Student("zhang",24);alert(stu2.fun());//显示zhang24妈妈 ,爸爸
这样存在一个问题:每次创建对象时都会把原型代码初始化一次,应该第一次初始化一次,之后就不用初始化了,所以在外面加一个判断
function Student (name,age){              this.name = name;           this.age = age;           this.family =['妈妈','爸爸'];    if(typeof this.fun! = 'function'){              alert("原型被初始化开始");Student.prototype.fun = function(){            return this.name + this.age+ this.family;    }      //注:动态原型模式只能这样写,不能 Student.prototype={} 这样直接给prototype赋值对象 alert("原型被初始化结束");
}
 }
var stu1 = new Student("liso",20);alert(stu1.fun());
var stu2 = new Student("zhang",24);alert(stu2.fun());
7、使用寄生构造函数:工厂模式+构造函数
function Student (name,age){   
            var obj = new Object();    obj.name=name;    obj.age = age;    obj.fun= function(){                   return this.name+this.age);           };return obj; } var stu = new Student("zhang",23); alert(stu.fun);
这种模式不能实现共享,不建议使用

8、使用稳妥构造函数:在一些安全的环境中,比如禁止使用this 和 new,这里的this是构造函数里不能使用this,这里的new是在外部实例化构造函数时不能使用new  function Person(name,age){     var obj = new Object();     boj.fun = function(){                     return name +age;//直接使用参数的值         }     rerun obj; } var person = Person("lisi",24);//不能使用new创建对象 alert(person.fun());//显示lisi24
了解这种模式就行


alert(Array.prototype.sort);//显示function sort(){}   说明sort是原型对象中的一个方法 String.prototype.substr // 如上sort
js内部定义的引用类型也都是含有原型的,并可以添加方法,但不建议这样使用,因为容易发生命名冲突

String.prototype.myStr = function(){            ---- 功能---- }        //给string的原型对象中添加一个方法