【深入JavaScript日记一】原型与原型链,词法作用域及动态作用域

开始前的碎碎念

计算机这门学科算是一门往前往后都看不到尽头的学科,我们能做的选择其中的一部分进行专精与深入,正所谓实力不足所以要提前开始准备,这样才能避开这个行业底层饱和中坚不足的现状,在最后拿到自己想要的offer,一起fighting!!


正文内容

原型、原型链

//举一个例子!!!!!!!!!!!!!!!!!!
    function Animal (name) {
        this.name = name;
    }

    Animal.prototype.color = 'white';
    Animal.prototype.weight = "1000kg";

    var cat1 = new Animal('大毛');
    var cat2 = new Animal('二毛');

    console.log(cat1.name);
    console.log(cat2.name);
    console.log(cat1.color);
    console.log(cat2.color);
    console.log(cat1.weight);
    console.log(cat2.weight);

输出结果:
输出
通过结果我们显而易见的发现,除了名字在构造时使用了传入的参数,两个cat又多出来了两个共有的属性,关键点在于这个prototypeprototype是一个只有函数具有的属性,它指向一个对象,这个对象就是调用该构造函数而创建的实例的原型。
那么原型就可以理解为每一个js对象在创建时(除了null),都会关联的一个对象(通俗理解为每生一个儿子都要告诉它爹是谁),每次创建的这个js实例都会“继承”下来这些共有的属性。

(补充:这里其实并不是真正的继承,继承意味着复制操作,但是 JavaScript 默认并不会复制对象的属性,JavaScript 只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些。)

我们通过查资料后发现了一个和prototype相对应的东西:__proto__,这是一个只有js实例具有的属性,通过验证,我们发现这个属性指向对象的原型。

console.log(cat1.__proto__===Animal.prototype);
//控制台打印 true,说明这俩代表的是一个东西

那这个里面究竟包含了什么东西呢,我们打印一下看看

    console.log(cat1.__proto__);
    console.log(Animal.prototype);

结果
我们惊奇的发现原型里还有一个 constructor,并且发现这个属性指向所关联的构造函数

    console.log(cat1.__proto__.constructor === Animal);
    console.log(Animal.prototype.constructor === Animal);
    //控制台打印了两个true!!!!!!

看到这里,我们捋一下:
prototype是函数具有的属性,指向原型
__proto__是js实例具有的属性,指向原型
constructor是原型所具有的属性,指向所关联的构造函数


于是我们可以大胆推测,在代码执行时,首先寻找实例的属性,找不到就会去实例的原型里找属性,找不到就一直找原型的原型。

    function Animal(name) {

    }

    Animal.prototype.color = 'white';//设置原型属性

    var cat1 = new Animal();
    cat1.color = "black";//设置实例属性

    console.log(cat1.color);  //black

    delete cat1.color;
    console.log(cat1.color);  //white

结果
显而易见,的确按照我们推测的那样,先找实例,再找原型,那如果原型也没有,那原型的原型又是什么,通过分析我们发现原型也是个对象,那一个对象的基类就是Object类咯,那我们再来试验一下。

    function Animal(color) {
        this.color = "white"
    }
    
    var cat1 = new Object();
    cat1.color = "black";

    console.log(cat1.color)
    console.log(Animal.prototype.color)//找原型

结果
通过实验我们发现了当实例的原型也没有该属性的时候,就会一路往上找,顺着思路,那最顶层原型的原型是什么呢,试验一下

	console.log(Object.prototype.__proto__);//顶层原型的原型  结果为null

结果也在意料之内,最顶端的地方就是万物的发源地,没有原型。看到这里,原型链也就可以理解为这一个个原型组成的链状结构。


词法作用域,动态作用域

作用域:就相当于规定一个变量有效的区域(比如你的公司万能门禁只能在公司范围内使用)
JavaScript 是采用词法作用域的,也就是静态作用域。
词法作用域:函数的作用域在函数定义的时候就决定了。
动态作用域:函数的作用域是在函数调用的时候才决定的。

    var val = 1;

    function A() {
        console.log(val);
    }

    function B() {
        var val = 2;
        A();
    }

    B();

比如这段代码:
采用静态作用域(js中的执行结果):首先执行A(),在函数内部没找到变量val,就去上一层寻找,找到了,于是输出1。
采用动态作用域:首先执行A(),在函数内部没找到变量val,然后去A()的作用域里寻找val,就是B()里,找到了val是2,所以输出2。


总结

prototype是函数具有的属性,指向原型
__proto__是js实例具有的属性,指向原型
constructor是原型所具有的属性,指向所关联的构造函数
在真正执行时查找顺序:实例属性--->原型属性--->原型的原型属性--->...--->顶层原型属性
原型就可以理解为每一个js对象在创建时(除了null),都会关联的一个对象
原型链可以理解为一个个原型组成的链状结构。

词法作用域:函数的作用域在函数定义的时候就决定了,js就是采用这种
动态作用域:函数的作用域是在函数调用的时候才决定的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AntyRia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值