JavaScript这门语言完全是面向对象的,也不可能以非面向对象的方法来使用。不过大多数编程新手的常见弱点在于按照功能编写代码,而不考虑任何上下文或者组织。
1 对象
对象是JavaScript的基础。事实上,这门语言里所有的东西都是对象。从最基本的层次上说,对象是一系列属性的集合。
两个创建简单对象并设置属性的例子
var obj = new Object()
// 给对象设置属性
obj.val = 5
obj.click = function() {
alert('hello')
}
var obj = {
// 用键值对方式来设置属性名和属性值
val: 5,
click: function(){
alert('hello')
}
}
2对象的创建
任何函数都可以被实例化为一个对象。
简单对象的创建和使用
// 一个简单的函数,接受名称并将其存入当前上下文中
function User(name) {
this.name = name;
}
// 指定名称来创建该函数的一个新对象
var me = new User('My name');
// 这个对象的名称被设置为自身的name属性了
alert(me.name == 'My name'); // true
// me是User对象的一个实例
alert(me.constructor == User) // true
// 既然User是一个函数,如果只把它作为函数来使用
User('test')
// 因为它的this上下文未曾设定,所以默认为全局的’window'对象
// window.name 等于提供的这个名字
alert(window.name == 'test') // true
constructor属性在每个对象中都存在,并一直指向创建它的函数。这样一来你就可以有效地复制对象了,用同一个基类创建对象并赋予不同的属性。
使用constructor属性的例子
function User(){}
var me = new User()
var you = new me.constructor()
// 两个对象的constructor实质是一致的
alert(me.constructor == you.constructor) // true
console.log(me.constructor == User) // true
console.log(you.constructor == User) // true
为对象添加上下文相关方法和属性
1. 公共方法
公共方法在对象的上下文中是最终用户始终可以接触到的。要实现这种在对象的每个实例都可以使用的公共方法,必须了解prototype(原型)的属性,这个属性包含了一个对象,该对象可以作为所有新副本的基引用。本质上说,所有对象原型的属性都能在该对象的每个实例中找到。
因为对象的原型任然是对象,和其他任何对象一样,可以给它们添加新的属性。
给原型添加属性的结果是由该原型实例化的每个对象都会获得这些属性,也就是这些属性公有化了。
对象的方法通过prototype对象添加的例子
function User (name, age) {
this.name = name
this.age = age
}
// 将一个新的函数添加到此对象的prototype对象中
// 其上下文是实例化后的对象
User.prototype.getName = function () {
return this.name
}
User.prototype.getAge = function () {
return this.age
}
var user = new User('Bob', 49)
console.log(user.getName()) // 'Bob'
console.log(user.getAge()) // 49
2. 私有方法
私有方法和私有变量只允许其他的私有方法、私有变量和特权方法访问。这种方法可以定义一些只让对象内部访问,而外部访问不到的代码。
只能由构造函数访问的私有方法的例子
function Classroom (students, teacher) {
// 用于显示所有班上学生的私有方法
function disp() {
console.log(students.join(','))
}
this.students = students
this.teacher = teacher
disp()
}
var classs = new Classroom (['John','Bob'], 'Mr. Smith')
// 调用disp方法会失败,因为它不是该对象的公共属性
classs.disp()
私有方法和私有变量在保持代码没有冲突的同时,允许你对用户能使用和能看到的内容有更好的控制。
3.特权方法
特权方法,用来指代那些在查看并处理私有变量的同时允许用户以公共方法的方法访问的方法。
使用特权的例子
function User (name, age) {
var year = (new Date()).getFullYear() - age;
// 创建一个特权方法,能够访问year变量,同事自身属于公共可访问的
this.getYearBorn =function(){
return year
}
}
var user = new User('Bob', 50)
console.log(user.getYearBorn())
// 注意,无法访问该对象私有的年份属性
console.log(user.year == null)
本质上,特权方法是动态生成的,因为它们是在运行时才添加到对象中的,而不是在代码第一次编译时就已近生成的。
动态生成方法的例子,这些方法在新对象实例化时创建的例子
// 创建一个新的用户对象,接受一个有许多属性的对象作为参数
function User (properties) {
// 遍历该对象的所有属性,并保证其作用域正确
for (var i in properties) {
(function(which){
var p = i;
// 创建此属性的一个新的读取器(getter)
which['get' + p] =function() {
return properties[p]
}
// 创建此属性的一个新的设置器
which['set' + p] =function(val) {
return properties[p] = val
}
})(this)
}
}
var user = new User({
name: 'Bob',
age: 50
})
// name 属性并不存在,因为它是属性对象的私有变量
console.log(user.name == null) // true
// 可以使用新的getname() 方法获得这个值
console.log(user.getname()) // Bob
// 能够使用新生成的函数来设置或获得年龄
user.setage(22)
console.log(user.getage()) // 22
4. 静态方法
不能在该对象的实例的上下文访问,而只属于主对象本身的那个上下文。
User.cloneUser = function(user){
return new User (
user.getName(),
user.getAge()
)
}