• 变量对象,作用域链,闭包,匿名函数,this关键字,原型链,构造器,js预编译,对象模型,执行模型,prototype继承


    想在js方面的水平有更进一步的提升,变量对象,作用域链,闭包,匿名函数,this关键字,原型链,构造器,js预编译,对象模型,执行模型,prototype继承这些概念肯定会经常碰到。

    这么多的概念,有点晕了吧。这里抓取几个关键字,讲故事 一样把这些概念给串起来。

    首先来看下对象的创建过程和函数对象的创建过程:

    对象创建过程:

    对象需要通过函数对象来创建。相当于java,c++语言通过类的构造函数创建。这里函数对象充当了类和构造函数的作用。

    new Fn(args)的创建过程如下:

    1,创建一个built-in object对象obj并初始化;

    2,根据Fn.prototype属性的类型给obj的[[prototype]]赋值。如果Fn.prototype为Object类型,则obj的[[prototype]]设置为Fn.prototype,否则为obj的初始化值(Object.prototype)。

    3,将obj作为this,使用args参数来调用Fn内部[[call]]方法;

      3.1 内部[[call]]方法创建当前执行上下文

      3.2 调用Fn的函数体

      3.3 销毁当前的执行上下文

      3.4 返回Fn的返回值,如果没有返回则返回undefined

    4,如果[[call]]的返回值是object,则返回这个值,否则返回obj;

    tip:

    1,每个对象都有一个隐式的[[prototype]]内部属性,每一个函数对象都有一个显式的prototype属性。

    demo:

    var Person = function () { };
    Person.prototype.Say = function () {
    alert("Person say");
    }
    Person.prototype.Salary = 50000;
    var Programmer = function () { };
    Programmer.prototype = new Person();
    Programmer.prototype.WriteCode = function () {
    alert("programmer writes code");
    };
    Programmer.prototype.Salary = 500;
    var p = new Programmer();
    p.Say();
    p.WriteCode();
    alert(p.Salary);  

    我们来做这样的推导:

    var p=new Programmer()可以得出p.__proto__=Programmer.prototype;

    而在上面我们指定了Programmer.prototype=new Person();我们来这样拆分,var p1=new Person();Programmer.prototype=p1;那么:

    p1.__proto__=Person.prototype;

    Programmer.prototype.__proto__=Person.prototype;

    由根据上面得到p.__proto__=Programmer.prototype。可以得到p.__proto__.__proto__=Person.prototype。

    好,算清楚了之后我们来看上面的结果,p.Say()。由于p没有Say这个属性,于是去p.__proto__,也就是Programmer.prototype,也就是p1中去找,由于p1中也没有Say,那就去p.__proto__.__proto__,也就是Person.prototype中去找,于是就找到了alert(“Person say”)的方法。

    其余的也都是同样的道理。

     函数对象创建过程

    无论是在js中自定义函数,还是调用Function创建函数,最终的调用形式都是:var newFun = Function(funcArgs,funcBody);

    函数对象的主要创建步骤如下:

    1,创建built-in object 对象 fn;

    2,将fn的[[prototype]]设置为Function.prototype;

    3,设置内部的[[call]]属性;

    4,设置内部的[[construct]]属性;

    5,设置fn.length为funcArgs.length,如果没有参数,设置为0;

    6,使用new Object 同样的逻辑创建一个Object对象fnProto

    7,将fnProto.constructor设为fn

    8,将fn.prototype设为fnProto

    9,返回fn

    js对象模型

    最后来解析下面几段代码:

    1,

    var name = 'king_z';
    function echo() {  
         alert(name);
         var name = 'pfzeng'; 
         alert(name);
         alert(age);
    } 
    echo();

    结果是:

    undefined
    pfzeng
    [脚本出错]

    2,

    function Foo() {};
    var foo = new Foo();
    Foo.prototype.label = "laruence";
    alert(foo.label); //output: laruence
    alert(Foo.label);//output: undefined

    参考网站:

    [1] http://www.laruence.com/jscss/page/2

    [2] http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html

    [3] http://www.cnblogs.com/zzcflying/archive/2012/07/20/2601112.html

  • 相关阅读:
    【LGOJ4147】玉蟾宫
    【BJWC2012】冻结
    【JSOI2016】最佳团体
    TCP三次握手是什么?为什么要进行三次握手?两次,四次握手可以吗?
    TCP 和 UDP的最完整的区别
    素数环问题为什么不能是奇数?
    malloc、calloc、new的区别
    请实现两个函数,分别用来序列化和反序列化二叉树
    int* &p 讲解
    c++中常用容器讲解
  • 原文地址:https://www.cnblogs.com/pfzeng/p/3225776.html
Copyright © 2020-2023  润新知