您的位置:首页 > Web前端 > JavaScript

js 构造函数和原型对象

2018-03-09 16:07 441 查看
1.构造函数 就是 用 new创建对象时调用的函数
使用构造函数的好处是 所有用同一个构造函数创建的对象 都具有同样的属性和方法
如果想创建多个相同的对象 可以创建自己的构造函数以及引用类型

构造函数也是函数 唯一的区别是构造函数应该首字母大写 以区别其他函数

function Person(){
// TODO
}

定义好构造函数后 就可以用它来定义对象

var person1 = new Person();
如果没有给定义构造函数的参数 可以忽略小括号
var person1 = new Person;

console.log(person1 instanceof Person)    // true

每个对象在创建时 都自动拥有一个构造函数的属性 其中包含了一个指向其构造函数的引用
那些通过对象字面量创建出来的 或 Object 构造函数创建出来的 泛用对象 其构造函数属性指向Object
那些通过自定义构造函数创建出来的对象 其构造函数属性指向创建它的构造函数

console.log(person1.constructor === Person)    // true

虽然实例及其构造函数之间存在这样的关系 但还是建议使用 instanceof 检查对象类型
因为构造函数属性可以被覆盖

使用构造函数的目的 是 创建许多拥有相同属性和方法的对象
function Person(name){
this.name = name;
this.sayName = function(){
console.log(name);
};
}

当调用构造函数时 new会自动创建this对象 其类型就是构造函数的类型
var person1 = new Person('bob);
person1.sayName();

你也可以在构造函数中显式调用return 如果返回值是一个对象
他会替代创建的对象实例返回
如果返回的值是一个原始类型 他会被忽略 新创建的对象实例会被返回

构造函数允许你用一致的方式初始化一个类型的实例
在使用对象前设置好所有的属性 如下

function Person(name){

Object.defineProperty(this, 'name', {
get: function(){
return name;
},
set: function(newName){
name = newName;
},
enumerable: true,
configurable: true
});

this.sayName = function(){
console.log(this.name);
};

}

始终确保使用new调用构造函数 否则就是改变全局对象 而不是创建一个新的对象

var person1 = Person('bob);

console.log(person1 instanceof Person);   //false
consoel.log(typeof person1);              //undefined
console.log(name);                        //bob

当Person 不是被new调用时 构造函数中的this对象 等同于 全局的 this对象
由于Person构造函数 依靠 new 提供返回值 person1 变量为 undefined

在严格模式下 当不通过 new调用Person构造函数时 会出现错误
因为 严格模式并不会为全局对象设置this this为 undefined 试图为undefined添加属性会出错

构造函数允许给对象配置同样的属性 但是 构造函数并没有消除代码冗余
每一个对象都有自己的sayName方法 这意味着 如果有100个对象实例 就有100个函数做相同的事

如果所有的对象实例共享同一个方法会更有效率 该方法可以使用this.name访问正确的数据 这就需要使用原型对象

2.可以把原型对象看做是对象的基类 几乎所有的函数(除了一些内建函数)都有一个名为prototype的属性
该属性是一个原型对象用来创建新的对象实例 所有创建的对象的实例共享该原型对象
且这些实例可以访问原型对象的属性 例如hasOwnProperty()方法被定义在泛用对象Object的原型对象中
但却可以被任何对象当做自己的属性访问

var book = {
title: 'book title'
}

console.log('title' in book);              // true
console.log(book.hasOwnProperty('title')); // true
console.log('hasOwnProperty' in book);     // true
console.log(book.hasOwnProperty('hasOwnProperty')); // false
console.log(Object.prototype.hasOwnProperty('hasOwnProperty')); // true

即使book中没有 hasOwnProperty的定义 仍然可以使用该方法
这是因为该方法的定义存在于 Object.protytype中
in操作符对原型属性和自有属性都返回true

鉴别原型属性
function hasPrototypeProperty(object, name){
return name in object && !object.hasOwnProperty('name')
}

console.log(hasPrototypeProperty(book, 'title'))           // false
console.log(hasPrototypeProperty(book, "hasOwnProperty"))  // true

3. prototype属性
一个对象实例 通过 内部属性 prototype跟踪其原型对象
该属性是一个指向该实例使用的原型对象的指针
当你用new 创建一个新的对象时
构造函数的原型对象会 被 赋给 该对象的protytype属性

可以调用Object.getPrototypeOf()方法读取 protytype属性的值
var object = {}
var prototype = Object.getPrototypeOf(object)
console.log(prototype === Object.prototype)

任何一个泛用对象 其 prototype 属性始终指向Object.prototype

大部分javascript引擎在所有对象上都支持一个名为_proto_的属性
该属性使你可以直接读写prototype属性
firefox safari chrome 和 nodejs都支持该属性 es6正在考虑将_proto_加入到标准中

isPrototypeOf 方法 检查某个对象是否是另一个对象的原型对象
var obj = {}
console.log(Object.prototype.isPrototypeOf(obj))   // true

当读取一个对象的属性时 js 引擎首先在该对象的自有属性中查找属性名字
如果找到则返回 如果自有属性中不包含改名字  则 js会搜索prototype中的对象
如果找到则返回  如果找不到  则返回 undefined

如果对象的 自有属性和原型属性相同  则 自有属性会覆盖原型属性
仅当自有属性被删除时 原型属性才会再次被使用
delete 操作符 仅对自有属性起作用
你无法删除一个对象的原型属性

无法给一个原型属性赋值
如果自有属性和原型属性同名
会在对象上创建一个新的自有属性 而不是改变原型属性

4.在构造函数中使用原型对象
原型对象的共享机制 使得他们成为一次性为所有对象定义方法的理想手段

function Person(name){
this.name = name;
}

Person.prototype.sayName = function(){
console.log(this.name);
};

var person1 = new Person('bob');

console.log(person1.name);
person1.sayName();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐