构造函数内部:
tips:
在构造函数内部通过this(用于指向当前对象)变量添加属性或方法,
此处定义的属性和方法都是为对象自身所拥有,
每次通过类创建实例时, this指向的属性都会得到相应的创建.
var Person = function(name, sex) {
// 私有属性: 只能被【私有方法】和【特权方法】访问
var contact = 'xxxxx@qq.com';
var number = '88888888';
// 私有方法: 在构造函数里声明, 能被【私有函数】【特权方法】访问, 只能访问【私有方法】和【私有属性】
var getInfo = function(name, sex) {
console.log('My name is ' + name + ', I’m a ' + sex + '!');
console.log('My email is ' + contact);
};
// 公有属性
this.name = name;
this.sex = sex;
// 特权方法: 可以访问【私有属性】【私有方法】【公有属性】
this.intro = function() {
getInfo(name, sex);
};
this.getContact = function(number) {
console.log(number);
};
// 构造器
this.getContact(number);
};
构造函数外部:
tips:
通过点语法定义的属性和方法不会添加到新创建的对象,因此类的实例无法访问, 只能通过类的自身(Person)访问.
// 类静态公有属性(对象不能访)
Person.isChinese = true;
// 类静态公有方法(对象不能访问到)
Person.speak = function() {
console.log('what???');
};
类的原型:
tips:
一种是为原型对象属性赋值, 另一种是将一个对象赋值给类的原型对象.
通过prototype继承的属性或方法是每个对象通过prototype访问到的,
所以每次通过类创建实例时, 这些属性和方法不会再次创建.
Person.prototype = {
// 显示指定对象的constructor属性
constructor: Person,
// 公有属性
hobby: 'reading',
// 公有方法
sport: function() {
console.log('run');
}
};
// test:
var tony = new Person('Tony', 'man', '25');
console.log('--- 访问【公有属性】 ---');
console.log(tony.name); // Tony
console.log(tony.sex); // man
console.log('--- 访问【特权方法】 ---');
console.log(tony.intro()); // My name is Tony, I’m a man!
// My email is xxxxx@qq.com
console.log('--- 访问【类静态公有属性】和【类静态公有方法】 ---');
console.log(tony.isChinese); // undefined
console.log(tony.speak()); // undefined
console.log('--- 通过类自身访问【类静态公有属性】和【类静态公有方法】 ---');
console.log(Person.isChinese); // true
console.log(Person.speak()); // what???
console.log('--- 访问【公有属性】及【公有方法】 ---');
console.log(tony.hobby); // reading
console.log(tony.sport()); // run
// 通过闭包实现:
var Person = (function() {
// 静态私有变量
var isChinese = true;
// 静态私有方法
var speak = function() {};
// 创建类
var _person = function() {
// 私有属性: 只能被【私有方法】和【特权方法】访问
var contact = 'xxxxx@qq.com';
var number = '88888888';
// 私有方法: 在构造函数里声明, 能被【私有函数】【特权方法】访问, 只能访问【私有方法】和【私有属性】
var getInfo = function(name, sex) {
console.log('My name is ' + name + ', I’m a ' + sex + '!');
console.log('My email is ' + contact);
};
// 公有属性
this.name = name;
this.sex = sex;
// 特权方法: 可以访问
this.intro = function() {
getInfo(name, sex);
};
this.getContact = function(number) {
console.log(number);
};
// 构造器
this.getContact(number);
};
// 构建原型
_person.prototype = {
constructor: _person,
// 公有属性
hobby: 'reading',
// 公有方法
sport: function() {
console.log('run');
}
};
// 返回类
return _person;
})();
类的两种写法
标准原型写法
function Person() {}
Person.prototype.sayHi = function() {}
var me = new Person();
console.log(me.constructor === Person); // true;
对象字面量
function Person() {}
Person.prototype = {
sayHi: function() {}
}
var me = new Person();
console.log(me.constructor === Person); // false;
console.log(me.constructor === Object); // true;
使用对象字面量的缺点:
使用对象字面形式改写原型对象改变了构造函数的属性,因此它现在指向Object而不是Person.
原因:
因为原型对象具有一个constructor属性,这是其他对象实例所没有的.
当一个函数被创建时,它的prototype属性也被创建, 且该原型对象的constructor属性指向该函数.
当使用对象字面形式改写原型对象Person.prototype时, 其constructor属性将被置为泛用对象Object.
解决:
在改写原型对象时手动重置其constructor属性.
// 对象字面量修正:
function Person() {}
Person.prototype = {
constructor: Person,
sayHi: function() {
console.log('Hi~');
}
}
var me = new Person();
console.log(me.constructor === Person); // true;
console.log(me.constructor === Object); // false;
创建对象的安全模式
var Person = function(name, sex) {
this.name = name;
this.sex = sex;
};
var tony = new Person('Tony', 'boy');
console.log(tony.name); // Tony
console.log(tony.sex); // boy
var anna = Person('Anna', 'girl');
console.log(window.name); // Anna
console.log(window.sex); // girl
console.log(anna); // undefined
console.log(anna.name); // Uncaught TypeError: Cannot read property 'name' of undefined
tips:
new可以看作是对当前对象this不停地赋值,
如果没有new, 则会直接执行函数, 因为函数在全局作用域中执行了,
所以在全局作用域中this指向的当前对象就自然是全局变量,
属性都添加到window上面了;
另外一个则因为Person类中没有return语句,
则函数执行完没有返回执行结果. 所以实例对象为undefined;
// 创建对象的安全模式
var Person = function(name, sex) {
// 判断执行过程中this是否是当前对象(如果是说明是用new创建的)
if(this instanceof Person) {
this.name = name;
this.sex = sex;
} else {
// 否则重新创建这个对象
return new Person(name, sex);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。