一、构造函数
构造函数就是一个普通函数,一般构造函数是首字母大写
构造函数执行流程
- 创建一个新对象 // 只要调用了 new Person() 立刻创建一个新对象
- 将函数的 this 指向新对象
- 执行函数中的代码
- 返回新对象
示例:
function Person(name){
this.name = name
this.alert_name = function(){
alert(this.name)
}
}
var per = new Person("tom")
per.alert_name()
二、原型prototype
1.我们创建的每一个函数,解析器都会向函数中添加一个属性 prototype , prototype就原型对象
2.当函数以构造函数形式调用时, 所创建的对象都有一个隐含的属性 __proto__ (两个下划线) 指向构造函数的原型对象 原型链指的就是 __proto__
// 1.创建的一个函数
function Person() {
}
// 2.以构造函数形式调用
var per = new Person()
// 对象的隐含属性 __proto__ 指向构造函数的原型对象
console.log(Person.prototype === per.__proto__) // true
原型是一个公工区域,所有同一个类的实例都可以访问到这个原型对象
当我们访问一个对象的属性或者方法时, 首先在自身寻找, 如果没有找到, 那么就会去原型中寻找, 原型中也没有, 那就去原型的原型, 直到找到Object, Object没有原型(Object.prototype 的 隐式原型是 null), 如果Object依然没有找到,则返回undefined
hasOwnProperty() 判断对象自身是否包含特定的属性(非继承)
function Person() {
}
var per = new Person()
// 向 Person 的原型对象中添加 run 方法
Person.prototype.run = function(){
console.log("我是原型上的run方法")
}
per.run(); // 我是原型上的run方法 ---自身没有 run 方法, 那么就会去原型中寻找
// per 和 Person 自身都不存在 run
console.log(per.hasOwnProperty('run')) // false
console.log(Person.hasOwnProperty('run')) // false
// 通过 __proto__ 和 prototype 访问原型对象,在原型中可以找到对应的属性
console.log(per.__proto__.hasOwnProperty('run')) // true
console.log(Person.prototype.hasOwnProperty('run')) // true
实例属性和静态属性
function Person(name) {
// name 是实例属性,需要通过 new 出来的实例访问
this.name = name;
// 实例方法
this.run = function () {
console.log(this.name + "-----run-----")
}
}
var per = new Person("Jack")
per.name; // Jack
// 静态属性
Person.age = 20
//向 Person 的添加静态方法
Person.sing = function(){
console.log("我是静态方法,直接挂在函数上,直接通过构造函数访问")
}
Person.sing(); // 我是静态方法,直接挂在函数上,直接通过构造函数访问
//实例属性/静态属性 都属于他们自身的属性,不会挂载到原型上
per.hasOwnProperty('name'); // true
Person.hasOwnProperty('sing'); // true
方法的继承
对象冒充继承: 无法继承原型上的属性和方法
原型链继承: 可以继承构造函数里的属性和方法,也可以继承原型链上的方法, 但是实例化子类时没办法给父类传参
function Person(name) {
this.name = name;
this.run = function () {
console.log(this.name + "-----run-----")
}
}
Person.prototype.work = function () {
console.log(this.name + "-----work-----")
}
function Chinese(name) {
Person.call(this, name) // 对象冒充继承 !!!!! name 会传递给父类
}
// 原型链继承 由于 对象继承已经继承了 构造函数里面的方法和属性 所以可以采用下面的写法只继承 原型链上的 属性和方法就可以
// Chinese.prototype = new Person()
Chinese.prototype = Person.prototype
var c = new Chinese("张三")
c.work() // 张三-----work----- !!!!!! 如果只使用原型链继承 那么将 输出 undefined-----work-----
c.run() // 张三-----run-----
三、构造函数(扩展)
1.var a = {} 其实是 var a = new Object() (a 的构造函数是 Object 函数)
2.var a = [] 其实是 var a = new Array() (a 的构造函数是 Array 函数)
3.function Foo(){...} 其实是 var Foo = new Function(...) (Foo 的构造函数是 Function 函数)
4.instanceof 判断一个对象是否是一个类的实例 ( 判断一个变量是否为数组: arr instanceof Array )