创建对象
创建对象的方式:
1. 字面量
2. new Object();
var stu1=new Object();
stu1.name="小明";
stu1.eat=function () {
console.log("吃米饭");
};
3.自定义构造函数
function Person(name,age) {
this.name=name;
this.age=age;
this.sayHi=function () {
console.log("我叫"+this.name+"今年"+this.age+"岁了");
};
}
//创建对象
var p=new Person("小白",20);
var p2=new Person("小黑",20);
//查看p是不是Person这种类型
p.sayHi();
console.log(p instanceof Person);//验证p是不是属于Person类型
5.工厂模式创建对象
function createObject(name,age,sex) {
//返回的是一个对象
return {
name:name,//前面的name是属性,后面的name是参数--变量
age:age,
sex:sex,
sayHi:function () {
console.log("您好,我叫:"+this.name);//this就是当前的对象
},
play:function () {
console.log("打游戏很好玩");
}
};
}
//来个学生对象
var stu1=createObject("卡卡西",28,"男");
stu1.sayHi();
var stu2=createObject("小段",38,"女");
-
构造函数和工厂函数的区别
共同点:都可以创建对象
不同点:
工厂函数:- createObject:有很明显的创建对象的代码:new Object
- 有return
- 函数名小写
- 不能非常的明确对象是属于什么类型.是Object类型
构造函数:
- 没有明显的创建对象
- 没有return
- 代码少于createObject的代码
- 把属性和方法直接给this
- this就是当前对象
- 函数名大写
- 非常的明确对象是属于Pearson类型,最终也是Object
原型:
-
原型的作用:数据共享,实现继承
-
构造函数中都有一个属性:prototype,叫原型,是程序员用的
实例对象中都有一个属性:_proto _,叫原型,是浏览器用的,不标准
无论是prototype还是__proto__都可/以看成是一个对象
构造函数中的原型(prototype)和实例对象中的原型(proto)都是属性,也都是对象
构造函数中的prototype和实例对象中的__proto__指向相同
实例对象的__proto__指向了构造函数的原型对象prototype
实例对象和原型对象之间的关系通过__proto__来联系,这个关系称为:原型链 -
原型的写法:
- 构造函数.prototype.属性=值
- 构造函数.prototype.方法=function—>函数.prototype,函数也是对象,所以,里面也有__proto__
- 实例对象.prototype-------->实例对象中没有这个属性,只有__proto__(暂时的)
-
通过原型可以为js内置对象添加原型的属性或者方法----->系统的内置对象的属性和方法可能不满足现在需求,所以,可以通过原型的方式加入属性或者方法,为了方便开发
String.prototype.方法=function(){};
var str=“哈哈”;
str.方法();---->实例对象可以直接调用原型中的属性或者方法 -
构造函数中的this和原型对象方法中的this指向相同,都是实例对象
//动物的构造函数----这里的属性和方法---不需要共享 function Animal(name,age) { this.name=name; this.age=age; this.play=function () { console.log("天天打豆豆"); }; } //希望性别数据是共享的,希望,吃的行为和跑的行为是共享的,希望玩的行为不是共享的 //通过原型添加属性和方法---->这些属性和方法会被共享,节省空间 Animal.prototype.sex="雌"; Animal.prototype.eat=function () { console.log("天天吃大骨头"); }; Animal.prototype.run=function () { console.log("一跑一蹦跶"); }; var dog=new Animal("小段",21); var cat=new Animal("小明",23); // 性别相同 console.log(dog.sex); console.log(cat.sex); //方法调用 dog.play(); cat.play(); //共享的方法调用 dog.eat(); cat.eat();
function my$(id) { return document.getElementById(id); } function ChangeStyle(btnObj,dvObj,json) { this.btnObj=btnObj;//按钮 this.dvObj=dvObj;//div this.json=json; this.init();//调用原型对象中的方法 } //向原型中添加方法 ChangeStyle.prototype.init=function () { var that=this;//保存对象 //为元素注册点击事件 this.btnObj.onclick=function () { //设置某个元素中样式多个属性的值 for(var key in that.json){ that.dvObj.style[key]=that.json[key]; } }; }; var json={ "backgroundColor":"yellow", "width":"500px", "height":"200px", "border":"2px solid blue" }; var cs=new ChangeStyle(my$("btn"),my$("dv"),json);//实例化对象
-
原型指向可以改变
实例对象的__proto__指向的是自己的构造函数的prototype,如果构造函数的prototype指向发生改变,那么实例对象的__proto__指向也改变(Person.prototype指向了什么地方,那么实例对象的__proto__也会指向那个地方);如果实例对象的原型指向改变了,再向原型中添加方法,那么这个方法被添加到了所改变指向的位置了 -
如果实例对象中的属性和原型对象中的属性重名,使用的是实例对象中的属性,原型对象中的该属性的值没有改变;如果实例对象中没有这个属性,但是,原型对象中有这个属性,那么就会使用原型对象中的该属性;使用的方式是需要的搜索,先在实例对象中找这个属性,有,则使用,没有则去原型对象中找,找到了就使用,没找到就是undefined
为什么这个属性的结果是undefined?因为js是一门动态类型的语言,该对象没有这个属性,点了,那么就有这个属性了,没有赋值,所以结果是undefined<body> <div id="dv"></div> <script> var dvObj=document.getElementById("dv"); console.dir(dvObj);//div // dvObj的原型链指向: //div--->HTMLDivElement.prototype---->HTMLElement--->Element--->Node--->EventTarget--->Object----null </script> </body>
-
面向对象的特性:封装,继承,多态
-
继承:在纯面向对象语言中,继承指的是类(class)与类(class)之间的关系,为了也是数据共享的问题,但是js是一门基于对象的语言,没有类的概念,但是,js可以模拟面向对象,可以把js中的构造函数当成是面向对象语言中的类来看待(可以使用构造函数来代替类)
// 组合继承 function Person(name) { this.name=name; } Person.prototype.sayHi=function () { console.log("人的打招呼"); }; function Student(name,age) { Person.call(this,name);//借用Person的构造函数实现继承,原型对象中的方法不能使用 this.age=age; } Student.prototype=new Person(); //使用组合继承 var stu=new Student("小白",20); console.log(stu.name,stu.age);//属性继承了 stu.sayHi(); console.dir(stu);//实例化对象stu显示出来 //组合继承:在Student中调用Person的构造函数,实现属性继承,改变Student的prototype的指向,指向的是Person对象的实例(改变prototype的指向) //借用构造函数+改变prototype指向--------->组合继承