昨天面试出了一道面试题 本人我做错了 于是痛定思痛 再过一遍面向对象
var name="一体机"; var value="infolist"; //构造函数 function Anbay(){ this.name="安备"; this.value="anbay"; } //原型 Anbay.prototype.show=function(message){ alert(this.name); alert(message); } //对象 var dbbackup={ name:"迪备", value:"dbbackup" } //实例 var anbay=new Anbay() anbay.show(this.value)//"安备" ,"infolist" 这里的this.value相当于window.value,构造函数被调用构造函数里面的this指向实例 anbay.show(dbbackup.value)//"安备","dbbackup" 这里的value是dbbackup里面的自然不用说,构造函数的作用域没有改变this.name弹出构造函数里面的dbbackup anbay.show.call(dbbackup,this.value)//"迪备","infolist" 这里的构造函数在对象dbbackup中执行,对象dbbackup拥有了所有的属性和方法
以下为个人测试得到的一些结果和数据
对理解面向对象很有用
1、属性类型 分为数据属性、访问属性
a.定义一个数据属性
/*var person={ } //属性所在的对象,属性的名字,和一个描述符对象 Object.defineProperty(person,"name",{ writable:false, value:"Ewarm" }) alert(person.name) delete person.name alert(person.name) var person={ } //属性所在的对象,属性的名字,和一个描述符对象 Object.defineProperty(person,"name",{ enumerable:true, value:"Ewarm" })
var person={} Object.defineProperty(person,"name",{ configurable:false, value:"Ewarm" }) delete person.name alert(person.name)//弹出Ewarm Object.defineProperty(person,"name",{ configurable:true, value:"Ewarm" })//抛出错误 不能被定义 Object.defineProperty(person,"name",{ writable:true, value:"cch" }) person.name="cch" alert(person.name)
b.定义一个访问属性
//访问器属性常用设置方式,即设置一个属性值会导致其他属性发生变化
var book={ _year:'2017', edition:1 }; Object.defineProperty(book,"year",{ get:function(){//get 读取 return this._year; }, set:function(newValue){ //set 写入 if(newValue>2017){ this._year=newValue; this.edition+=newValue-2017 } } }) book.year=2018; alert(book.edition) alert(book._year)
//c.定义访问器的旧方法
var book={ _year:'2017', edition:1 } book.__defineGetter__("year",function(){ return this._year }) book.__defineSetter__("year",function(newValue){ if(newValue>2017){ this._year=newValue; this.edition+=newValue-2017 } }) book.year=2018 alert(book.edition)//2
//d.定义多个属性
var book={} Object.defineProperties(book,{ _year:{ writable:true, value:2017 }, edition:{ writable:true, value:1 }, year:{ get:function(){ return this._year; }, set:function(newValue){ if(newValue>2017){ this._year=newValue; this.edition+=newValue-2017 } } } }) var descriptor=Object.getOwnPropertyDescriptor(book,"_year");//数据属性 alert(descriptor.value) alert(descriptor.configurable)//用Object.defineProperties 这种configure默认为 false alert(descriptor.enumerable) alert(typeof descriptor.get); var descriptor=Object.getOwnPropertyDescriptor(book,"year"); alert(descriptor.value); alert(descriptor.enumerable); alert(typeof descriptor.get);
2.创建对象
//a.工厂模式
function createPerson(name,age,job){ var o=new Object(); o.name=name; o.age=age; o.job=job; o.sayName=function(){ alert(this.name) } return } var person1=createPerson("Ewarm",18,"software Engineer") var person2=createPerson("CCH",18,"doctor")
//b.构造函数
function Person(name,age,job){ this.name=name; this.age=age; this.sayName=function(){ alert(this.name) } } var person1=new Person() var person2=new Person() var person=new Person("Ewarm",18,"software Engineer")
//1.当构造函数调用
person.sayName()
Person("Greg",27,"Doctor");
//2.当普通函数调用
window.sayName()
//3.在另一个对象的作用域中调用
var o =new Object() var o={ character:"smart", name:"Ew", age:25, job:"Nurse" } console.log(o) Person.call(o,"cch",18,"nurse")//就是说这个构造函数 在o里面执行并且o里面的该有还是有 调用之后 之前的会被覆盖 没有的会被加上在o里面 o.sayName() console.log(o)
//4.原型模式
function Person(){ } Person.prototype.name="Ewarm"; Person.prototype.age="29"; Person.prototype.job="software Engineer"; Person.prototype.sayName=function(){ alert(this.name); } var person1=new Person() //我们可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系,即实例.__proto__是否指向构造函数的原型对象,如果指向那么这个方法返回为ture。 alert(Person.prototype.isPrototypeOf(person1))//true //ECMAScript5增加了一个新方法 Object.getPrototype() 这个方法返回的是实例.__proto__的值,即构造函数原型对象 alert(Object.getPrototype(person1)==Person.prototype)//emmmm 我用的谷歌 报错了 说是支持可以实现了但没实现
注意:当我们要读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从对象实例开始 问:你有没有我要的东西。如果有返回该属性的值。
如果没有继续往下面查找继续搜索指针指向的原型对象,在原型对那个中查找具有指定名字的属性,如果有返回该属性,如此一直到顶层Object。prototype,还没有返回undefine
原型有好多小细节 使用原型继承存在问题 但有解决的方法 这里我们先只说创建对象这一块
//5.组合使用构造函数和原型模式
//6.动态原型模式
//7.寄生构造函数模式
//8.稳妥构造函数模式