原型 this指向

62 阅读2分钟

原型

function Person(name, age) {
    this.name = name
    this.age = age
    this.sayHi = function () {
        return "你好" + this.name
    }
}
var student = new Person("小明", 18)

通过构造函数可以创建可以用户对象
每个用户对象中的sayHi方法都是完全一样的
创建多个用户对象会造成内存空间的浪费
要解决这个问题 必须学会原型
1.原型
每个函数都会自动附带一个属性prototype,这个属性的值是一个普通对象

2.实例
通过new产生的对象称之为实例
因为js中的对象都是通过new产生的,可以称js中的所有对象为实例
上面一段代码中的student对象为Person构造函数创建的实例

对象
var obj = { a: 1 }
实际js内部执行
var obj = new Object()
obj.a = 1

数组
var arr = [1, 2, 3]
实际js内部执行
var arr = new Array(1,2,3)

函数

function demo(a, b) {
    return a + b
}

实际js内部执行

var demo = new Function("a", "b", "return a + b")

3.隐式类型
每个实例中都有一个特殊的属性__proto__,称之为隐式类型,它指向构造函数的原型,所以 Person.prototype === student.__proto__

原型总结 当访问实例时,先找自身属性,如果自身属性没有,将寻找实例的隐式原型(即构造函数的原型),总结得知开头代码可以改为

function Person(name, age) {
    this.name = name
    this.age = age
}
Person.prototype.sayHi = function () {
    return "你好" + this.name
}
var student = new Person("小明", 18)
console.log(student.sayHi());

打印结果为:你好小明

this

this只有两种情况
第一种是在全局种使用 this指向window
第二种是在函数中引用,this指向取决于函数如何调用

function Demo() {
    console.log(this);
}

调用方式 new

new Demo()
打印结果为空对象

Demo()
打印为 window

通过对象调用

var obj = {
    a: 1,
    b: 2,
    method: function () {
        console.log(this)
    }
}
obj.method()

打印这个对象

call

function Obj(a) {
    console.log(this, a)
}
var arr = [1, 2, 3]
Obj.call(arr, 1)

打印结果为[1,2,3] 1

apply 与call 不同的地方为第二个形参不一样,apply第二个形参需要传数组,除此之外功能相同

function Obj(a, b, c) {
    console.log(this, a, b, c)
}
var arr = [1, 2, 3]
Obj.apply(arr, [1, 3, 5])

打印结果为 [ 1, 2, 3 ] 1 3 5

判断对象中的属性是本身就有的 还是在原型上查出的
hasOwnProperty()

Obj.prototype.b = 2
function Obj(a) {
    this.a = a
}
var c = new Obj(1)
console.log(c.b);
console.log(c.hasOwnProperty("b"))
console.log(c.hasOwnProperty('a'))

打印结果为:2 false true

判断对象中是否包含该属性(包括原型)
in

function Obj(a) {
    this.a = a
}
Obj.prototype.b = 2
var c = new Obj(1)
console.log('a' in c);
console.log('b' in c);

打印结果为 true true