面向对象的程序设计
属性类型
数据属性
[[Configurable]]:是否能通过delete删除属性,默认为true
[[Enumberable]]:是否能通过for-in返回属性,默认为true
[[Writable]]:能否修改属性的值,默认为true
[[Value]]:数据
改变上述属性
Object.defineProperty()
var person = {}
Object.defineProperty(person,"name",{
writable: false, //不能重写
value: "123",
configurable: false, //以后再也不可配置
enumerable: true
})
console.log(person.name) //123
person.name = "456"
console.log(person.name) //123
访问属性
[[Configurable]]:是否能通过delete删除属性,默认为true
[[Enumberable]]:是否能通过for-in返回属性,默认为true
[[Get]]:读取属性的时候调用的函数
[[Set]]:写入属性的时候调用的函数
var book = {
year: 2017,
edition: 1
}
Object.defineProperty(book,"month",{ //对month进行访问
get: function(){
return "123"
},
set: function(newValue){
if(newValue>2017){
this.year = newValue
}
}
})
book.month = 2018 //调用set
console.log(book.year)
console.log(book.month) //get方法返回123
访问多个属性
var book = {
year: 2017,
edition: 1
}
Object.defineProperties(book,{
edition:{
writeable:true,
value: 2015
},
month:{
get: function(){
return "123"
},
set: function(newValue){
if(newValue>2017){
this.year = newValue
}
}
}
})
book.month = 2018
console.log(book.year) //2018
console.log(book.month) // 123
console.log(book.edition) //2015
获得属性 Object.getOwnPropertyDescriptor()
var descriptor = Object.getOwnPropertyDescriptor(book,"year")
console.log(descriptor)
创建对象
最合适的方法–构造函数模式和原型模式
function Person(name , age){
this.name = name
this.age = age
}
Person.prototype = {
constructor: Person,
sayName: function(){
console.log(this.name)
}
}
var john = new Person("john")
john.sayName() //john
此类方法属性不共享,方法共享
其他要点
1.可将构造函数当普通函数用,原型中不行,只能在构造函数模式中
function Person(name , age){
this.name = name
this.age = age
sayName = function(){
console.log(this.name)
}
}
Person("john")
window.sayName() //john
2.内存区问题 sayName()在同一内存区
function Person(name , age){
this.name = name
this.age = age
}
Person.prototype = {
constructor: Person,
sayName: function(){
console.log(this.name)
}
}
var person1 = new Person("john")
var person2 = new Person("john2")
console.log(person1.sayName == person2.sayName)
另一种情况 sayName在不同内存区(没有this是true)
function Person(name , age){
this.name = name
this.age = age
this.sayName = function(){
console.log(this.name)
}
}
var person1 = new Person("john")
var person2 = new Person("john2")
console.log(person1.sayName == person2.sayName) //false
原型–>我的理解是一个实例,所有其他实例的父类
isPrototypeOf()验证是否为某原型的实例
Person.prototype.isPrototypeOf(person1) //true
hasOwnProperty()检测属性是否存在于实例中
person1.hasOwnProperty(“name”)
function Person(){}
Person.prototype = {
name : "name",
age : "age",
sayName: function(){
console.log(this.name)
}
}
var person1 = new Person()
console.log(person1.hasOwnProperty("name")) //false
person1.name = "123"
console.log(person1.hasOwnProperty("name")) //true
原型与继承
每个构造函数都有原型,每个原型都有指针指向构造函数,每个实例都有指向原型的指针
function Animal(){}
Animal.prototype = {
constructor: Animal
//__proto__
}
function Dog(){}
Dog.prototype ={
constructor: Dog
//__proto__
}
Dog.prototype = new Animal() //继承
let dog1 = new Dog()
console.log(dog1)
//Dog.__proto__ = Animal
//Animal.__proto__ = Object
每个实例中都有proto指向new的类,若没有则指向本身
原型与实例的关系
instance intanceof Object
Object.prototype.isPrototypeOf(intance)
最常用的继承模式–组合继承
function Super(){
this.property = true
}
Super.prototype.getSuperProperty = function(){
return this.property
}
function Sub(){
this.subProperty = false
Super.call(this)
}
Sub.prototype = new Super()
Sub.prototype.getSubProperty = function(){
return this.subProperty
}
let inte = new Sub()
console.log(inte.getSuperProperty())
console.log(inte.getSubProperty())
注意子类不能使用字面量的方法如下所示,它会重写了原型链,父类可以用字面量写法
Sub.prototype = {}
我最常用的方法–野路子
function Super(){
this.property = true
}
Super.prototype = {
constructor: Super,
getSuperProperty: function(){
return this.property
}
}
function Sub(){
this.subProperty = false
Super.call(this)
}
Sub.prototype = {
constructor: Sub,
getSubProperty: function(){
return this.subProperty
},
__proto__: Super.prototype
}
let inte = new Sub()
console.log(inte.getSuperProperty()) /true
console.log(inte.getSubProperty()) /false
面向对象的程序设计
https://zhangfuli.github.io/2017/09/25/面向对象的程序设计/