在构造函数内部经过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); };
经过点语法定义的属性和方法不会添加到新建立的对象,所以类的实例没法访问, 只能经过类的自身(Person)访问.闭包
// 类静态公有属性(对象不能访) Person.isChinese = true; // 类静态公有方法(对象不能访问到) Person.speak = function() { console.log('what???'); };
一种是为原型对象属性赋值, 另外一种是将一个对象赋值给类的原型对象.
经过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; })();
标准原型写法this
function Person() {} Person.prototype.sayHi = function() {} var me = new Person(); console.log(me.constructor === Person); // true;
对象字面量prototype
function Person() {} Person.prototype = { sayHi: function() {} } var me = new Person(); console.log(me.constructor === Person); // false; console.log(me.constructor === Object); // true;
使用对象字面形式改写原型对象改变了构造函数的属性,所以它如今指向Object而不是Person.code
由于原型对象具备一个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
new能够看做是对当前对象this不停地赋值,
若是没有new, 则会直接执行函数, 由于函数在全局做用域中执行了,
因此在全局做用域中this指向的当前对象就天然是全局变量,
属性都添加到window上面了;
另一个则由于Person类中没有return语句,
则函数执行完没有返回执行结果. 因此实例对象为undefined;ip
// 建立对象的安全模式 var Person = function(name, sex) { // 判断执行过程当中this是不是当前对象(若是是说明是用new建立的) if(this instanceof Person) { this.name = name; this.sex = sex; } else { // 不然从新建立这个对象 return new Person(name, sex); } }