一、JavaScript创建对象的方法
1.js直接创建对象:(好处:创建简单)(弊端:无法量产)
例如:创建一个学生对象:名称,年龄 方法:吃饭,产生多个学生对象
var student={
name:'陈奕迅',
age:21,
eat:function(){
console.log(this.name+"正在吃")
}
}
var s1={
name:'彭于晏',
age:22,
eat:function(){
console.log(this.name+"正在吃")
}
}
var s2={
name:'吴彦祖',
age:23,
eat:function(){
console.log(this.name+"正在吃")
}
}
console.log(student)
console.log(s2)
2.工厂模式:通过函数来创建对象(好处:可以量产对象)(弊端: 无法明确对象的类型 ,全都是object类型的,无法类型的细分)
工厂模式是一种众所周知的设计模式,广泛应用于软件工程领域,用于抽象创建特定对象的过程。
重复的创建对象 ,需要创建时可以快速的创建出来
将创建对象的过程 封装到函数内部 ,直接调用函数进行对象创建
function Student(name,age){
var s=new Object()
s.name=name
s.age=age
s.eat=function(){
console.log(this.name+'正在吃')
}
return s
}
function Teach(name,age){
var t=new Object()
t.name=name
t.age=age
t.eat=function(){
console.log(this.name+'正在吃')
}
return t
}
var s1=Student("王一",21) //object
var t1=Teach("张三",30)
console.log(s1)
例如以后做一个学生管理系统 判断对象是属于老师还是学生就用 instanceof 检测变量的数据类型
(变量 instanceof 类型 ) 返回布尔值
console.log(t1 instanceof Teach)// false
typeof 返回对应变量的数据类型 返回根本数据类型 字符串
例如:
var arr=[1,2,3]
var num=10
var num=new Number(10)
//arr变量 检测arr变量是否为数组类型
console.log(typeof(num)) // number
console.log(num instanceof Object)//false
3.构造函数模式:(好处:可以明确对应的对象类型)
(弊端:不同对象中的相同方法,无法公用,需要独立存储,造成内存损耗)
其他的编程语言当中,想要创建对象的话,创建一个类。 类:一类事物的统称 包含 属性和方法
js中没有类概念 构造函数的方式来模拟类!!! 利用js this指向性可以改变的问题
创建一个学生类(构造函数) name,age,eat方法。
this指向 对象 window 固定对象 事件源 。 this指向 对象 window 固定对象 事件源
例如:
//window对象
function fun(){
console.log(this)//window
}
fun()
开始创建构造函数模式:
function Student(name,age){
this.name=name
this.age=age
this.eat=function(){
console.log(this.name+"正在吃")
}
}
function Teach(name,age){
this.name=name
this.age=age
this.eat=function(){
console.log(this.name+"正在做")
}
}
//通过new来创建对象 new做了什么?
// 1.创建一个空对象 {}
// 2.在执行函数的过程中 ,函数内部 this指向创建出来的{} this={} {name:"王一",age:21,eat:function(){}}
// 3.将创建对象 返回出来,赋值给前方变量
var s1=new Student("王一",21)
var s2=new Student("王二",22)
var t1=new Teach("王六",44)
console.log(s1)//Student {name: '王一', age: 21, eat: ƒ}
console.log(t1)//Teach {name: '王六', age: 44, eat: ƒ}
//判断s1是否为学生类型的对象
console.log(s1 instanceof Student)//true
console.log(t1 instanceof Teach)//true
// console.log(s2)
//Prototype属性 :原型对象
//想办法将 公有的方法或者属性 放到原型中呢
//通过同一个构造函数创建出来的对象原型是相等的
//对象的原型__proto__
console.log(s1.__proto__==s2.__proto__)//true
// s1中eat方法 s2也有eat方法 造成内存的消耗
console.log(s1.eat==s2.eat)//false
var t1=new Teach("张三",24)
console.log(t1)//Teach {name: '张三', age: 24, eat: ƒ}
//判断s1是否为学生类型的对象
console.log(s1 instanceof Student)//true
console.log(t1 instanceof Teach)//true
// console.log(s1)
在上面这个代码例子中,构造函数代替了工厂工厂函数,实际上两个内部代码的内容基本是一样的,只是有以下区别:
1.没有显式地创建对象。 2.属性和方法直接赋值给了this。 3.没有return。
另外要注意函数名Student的首字母大写,按照惯例构造函数名称的首字母都是要大小写,非构造函数则以小写字母开头。这是从面向对象编程语言那里借鉴的,有助于在ECMAScript中区分构造函数和普通函数。毕竟ECMAScript的构造函数就是能创建对象的函数。
4.原型创建:
每一类相同的对象 ,原型对象都是一个样 ,想办法将公有的方法 放到原型中
如下代码:
//创建一个学生构造函数 name,age eat公有方法
//构造函数原型 ==实例化对象的原型
//将共有的方法放入构造函数的原型中
function Student(name,age){
this.name=name
this.age=age
}
Student.prototype.eat=function(){
console.log(this.name+'正在吃')
}
var s1=new Student("王一",21)
s1.__proto__.eat=function(){
console.log(123)
}
console.log(s1)
s1.eat() //123
// s1.eat()
var s2=new Student("王二",22)
s2.eat() //123
// s2.eat()
// console.log(s1.eat==s2.eat)//true
// s1.eat()
// console.log(s2)
//实例化对象的 s1.__proto__
//构造函数的原型 Student.prototype
// console.log( s1.__proto__==Student.prototype) //true
实际上,这个对象就是通过调用构造函数创建的对象原型。使用原型对象的好处是,在它上面定义的属性和方法可以被对象实例共享。原来在构造函数中直接赋值给对象实例的值,可以直接赋值给它们的原型。(关于原型模式更详细的解释可参考:JavaScript高级程序设计第四版第224页)
二、对象
1.对象方法:
//instanceof 检测变量的(对象的)类型
function Student(name,age){
this.name=name
this.age=age
this.eat=function(){
console.log('干饭')
}
}
Student.prototype.showInfo=function(){
console.log(this.name+this.age)
}
function Teacher(name,age){
this.name=name
this.age=age
}
var s1=new Student("刘桑",21)
var t1=new Teacher("王桑",22)
//*!!*构造函数原型上的方法: isPrototypeOf() 检测当前对象是否基于对应的构造函数创建出来的
var result=Student.prototype.isPrototypeOf(t1)
console.log(result)
// t1 instanceof Student instanceof 检测变量的数据类型 ,对应变量必须为原型创建出来的
//有时候面试题会出下面这种方法 但其实和上面的意思一样
// if(Student.prototype.isPrototypeOf(t1)){
// }
//
// ***判断属性方法
// 判断 属性或者方法 是 否属于 构造函数内部 第一个方法:.hasOwnProperty(属性)
// 判断s1的name属性是否属构造内部的
var r=s1.hasOwnProperty("name")
console.log(r)//true
// var r=s1.hasOwnProperty("showInfo")
// console.log(r) //false
//***判断当前对象是否具有对应属性 in
//key in 对象
// var r= "color" in s1
//console.log(r)
//面试题:封装一个方法 传入 一个对象 key,判断这个key是否属于对象的原型上,返回布尔值
// 怎么判断基于原型? 1.对象需要具有key 2.这个属性不是构造函数里面的
// hasProtoType(s1,"name")
function hasProtoType(obj,key){
// if(key in obj){
// //判断是否在构造函数里
// if(obj.hasOwnProperty(key)){
// return false
// }else{
// return true
// }
// }else{
// //key不在obj中
// return false
// }
return key in obj && obj.hasOwnProperty(key)==false
}
var r1=hasProtoType(s1,"aaa")
console.log(r1)