JS梳理-new、this、原型、原型链

136 阅读1分钟

1. JS中的new关键字做了什么?

先说结论:

    1. new是JS语言的设计核心,以new为中心衍生出了几个JS核心概念:this、原型等;
    1. new是为了节约内存和代码量而创建的语法糖;
    1. new帮我们把对象的共有属性放在原型里,实现了绑定原型;
    1. new帮我们把对象的自身属性放在自己的构造函数里,执行构造函数;
    1. new帮我们指定了this= 临时对象,创建了临时对象,并返回临时对象。

举个游戏中创建Soldier的栗子:

let soldier = {
    ID:1,
    kind:American GI,
    attack:8,
    hp:56,
    move:function(){},
    run:function(){},
    attact:function(){},
    defence:function(){}
}
Camp.construct(soldier)    
function soldier(ID){
    let 临时对象 = {}  // new 创建临时对象
    临时对象.__proto__ = sodier.原型  // new 绑定原型
    临时对象.ID = ID
    临时对象.hp = 56
    return 临时对象   // new 帮我们return
}

soldier.原型 = {
    kind:American GI,
    attack:8,
    hp:56,
    move:function(){},
    run:function(){},
    attact:function(){},
    defence:function(){}
}
  • new来写:
function solider(ID){
    this.ID = ID
    this.hp = 56
}
solider.prototype = {
    kind:American GI,
    attack:8,
    hp:56,
    move:function(){},
    run:function(){},
    attact:function(){},
    defence:function(){}
}
  • 创建solider
let soliders = []
for(var i=0; i<100; i++){
    soliders.push(new solider(i))
}

Camp.construct(soldiers)  
  • 再看字面量定义数组
a = []
a = new Array()

2. JS中的this是什么?

先说结论:

  • this就是call函数的第一个传入参数

从函数的三种调用形式说起:

f(p1, p2)
obj.child.method(p1, p2)
func.call(context, p1, p2) // 正常调用形式,其余上面2种是他的语法糖
  • 分别把上面两行代码做转换后:
f.callundefined, p1,p2)

本例中的undefinedf.call函数的第一个传入参数,即为this,同时浏览器发现thisundefined就会转成window

  • 再举个栗子
obj.child.say()

本例中的假如obj是一个对象,child是他的一个属性,其属性名为child,其属性值存的一个地址#404,这个地址指向另一个对象,这个对象有一个属性,其属性名为say,其属性值存的另一个地址#505,这个地址指向另一个函数对象。

image.gif

综上,函数对象是不属于obj或obj.child对象的,正因为函数和对象是没有任何关系的,所以需要把这个对象传给函数,如果不传参数,函数就不知道是哪个对象调用它,需要接收obj.child这个传入参数,函数在调用时得知道是哪个对象存着它,f.call(obj.child)

3. JS中的原型链是什么?

  • 要解释原型链,需要先说明一下原型,举个栗子:

假设有一个普通对象x={ },这个x会有一个隐藏属性y,这个y会指向Object.prototype,即x.y = Object.prototype,x的原型是Object.prototype

y的唯一作用就是用来指向x的原型的,若没有y,x就不知道自己的原型是谁了

  • 接下来说一说原型链,再举个栗子:

假设有一个数组对象a=[],这个a会有一个隐藏属性y,这个y会指向Array.prototype,即a.y=Array.prototype,a的原型是Array.prototype

与上例普通对象x是一样的,但是不一样的是a的原型Array.prototype也有一个隐藏属性z,指向Object.prototype,即Array.prototype.z=Object.prototype 这样一来,a就有两层原型:

a的原型是Array.prototype;a的原型的原型是Object.prototype,于是就通过隐藏属性z形成了一个链条,这就是原型链

a ==> Array.prototype ==> Object.prototype

原型链解决了在没有class类的情况下,实现继承。

参考

jirengu.com