原型_原型链 - CSDN
精华内容
参与话题
  • JavaScript原型原型

    2020-05-29 11:04:27
    http://zhangjiahao8961.iteye.com/blog/2070650

    http://zhangjiahao8961.iteye.com/blog/2070650

    总结:

    1. 在 JavaScript 中,函数(function)是允许拥有属性的。所有的函数会有一个特别的属性 prototype;
      如 Function.prototype 或者 Object.prototype 又或者我们自己定义的函数或对象;
    Function.prototype 
    Object.prototype 
    
    
    function doSomething(){}
    console.log( doSomething.prototype );
    // 和声明函数的方式无关,
    // JavaScript 中的函数永远有一个默认原型属性。
    var doSomething = function(){};
    console.log( doSomething.prototype );
    
    
    1. 当谈到继承时,JavaScript 只有一种结构:对象。
      每个实例对象( object )都有一个私有属性(称之为 proto指向它的构造函数的原型对象(prototype )
    function doSomething(){}
    // 和声明函数的方式无关,
    // JavaScript 中的函数永远有一个默认原型属性。
    var doSomething = function(){};
    
    
    var doSomethingInstance = new doSomething();
    console.log(doSomethingInstance)
    // 每个实例对象都有一个 __proto__ 属性;
    
    {
        constructor: ƒ doSomething(),
        __proto__: {
            constructor: ƒ Object(),
            hasOwnProperty: ƒ hasOwnProperty(),
            isPrototypeOf: ƒ isPrototypeOf(),
            propertyIsEnumerable: ƒ propertyIsEnumerable(),
            toLocaleString: ƒ toLocaleString(),
            toString: ƒ toString(),
            valueOf: ƒ valueOf()
        }
    }
    
    // 既有如下功能;
    
    doSomething.__proto__ = doSomething.prototype
    
    
    1. 几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。

    2. 构造函数

    原型对象prototype中都有个预定义的constructor属性,用来引用它的函数对象。这是一种循环引用
    
    person.prototype. constructor === person  //true
    
    Function.prototype.constructor === Function //true
    
    Object.prototype.constructor === Object //true
    
    
    1. 图解
    var  person  =  function(name){
    	this.name = name
    };
     person.prototype.getName = function(){
            return this.name;
     }
    
     var ziji = new person(‘koala’);
     ziji.getName(); //koala
    

    在这里插入图片描述
    6. 原型继承

    方法一:

    function foo(){}
    foo.prototype = {
      foo_prop: "foo val"
    };
    
    function bar(){}
    var proto = new foo;
    proto.bar_prop = "bar val";
    bar.prototype = proto;
    
    var inst = new bar;
    console.log(inst.foo_prop);
    console.log(inst.bar_prop);
    

    优点:支持目前以及所有可想象到的浏览器(IE5.5都可以使用). 这种方法非常快,非常符合标准,并且充分利用JIST优化。

    缺点:为使用此方法,这个问题中的函数必须要被初始化。 在这个初始化过程中,构造可以存储一个唯一的信息,并强制在每个对象中生成。但是,这个一次性生成的独特信息,可能会带来潜在的问题。另外,构造函数的初始化,可能会给生成对象带来并不想要的方法。 然而,如果你只在自己的代码中使用,你也清楚(或有通过注释等写明)各段代码在做什么,这些在大体上都根本不是问题(事实上,还常常是有益处的)。

    方法二:

    function foo(){}
    foo.prototype = {
      foo_prop: "foo val"
    };
    
    function bar(){}
    
    var proto = Object.create(
      foo.prototype
    );
    
    proto.bar_prop = "bar val";
    bar.prototype = proto;
    
    var inst = new bar;
    console.log(inst.foo_prop);
    console.log(inst.bar_prop);
    
    // 或者
    
    function foo(){}
    foo.prototype = {
      foo_prop: "foo val"
    };
    function bar(){}
    
    var proto = Object.create(
      foo.prototype,
      {
        bar_prop: {
          value: "bar val"
        }
      }
    );
    bar.prototype = proto;
    
    var inst = new bar;
    console.log(inst.foo_prop);
    console.log(inst.bar_prop)
    

    优点:支持当前所有非微软版本或者 IE9 以上版本的浏览器。允许一次性地直接设置 proto 属性,以便浏览器能更好地优化对象。同时允许通过 Object.create(null) 来创建一个没有原型的对象。

    缺点:不支持 IE8 以下的版本。然而,随着微软不再对系统中运行的旧版本浏览器提供支持,这将不是在大多数应用中的主要问题。 另外,这个慢对象初始化在使用第二个参数的时候有可能成为一个性能黑洞,因为每个对象的描述符属性都有自己的描述对象。当以对象的格式处理成百上千的对象描述的时候,可能会造成严重的性能问题。

    展开全文
  • __proto__:所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型) prototype:所有函数拥有prototype属性(显式原型)(仅限函数) constructor所有prototype都有一个 constructor 属性指向关联的构造...

    点击查看“构造函数的五种继承方式


    构造函数

    通过 new 函数名 来实例化对象的函数叫构造函数。任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要 功能为 初始化对象,特点是和new 一起使用。new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。构造函数定义时首字母大写(规范)。

    function Person(name) {
        this.name = name;
    }
    let p1 = new Person('张三'); // 实例化
    console.log(p1); //Person {name: "张三"}
    

    此时,p1就是一个新对象。

    new一个新对象的过程,发生了什么?

    1. 创建一个空对象obj {}
    2. 空对象的_proto_指向了构造函数的prototype成员对象
    3. 使用apply调用构造器函数,属性和方法被添加到 this 引用的对象中
    4. 如果构造函数中没有返回其它对象,那么返回 this,即创建的这个的新对象,否则,返回构造函数中返回的对象

    对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。
    .

    手写new函数

    function _new(func, ...args) {
        // 1. 创建空对象
        let obj = {};
        // 2. 空对象的_proto_指向了构造函数的prototype成员对象
        obj.__proto__ = func.prototype; // 一二步合并就相当于 let obj = Object.create(func.prototype)
        // 3. 使用apply调用构造器函数,属性和方法被添加到 this 引用的对象中
        let result = func.apply(obj, args);
    	// 4. 确保 new 出来的是个对象
        return typeof result === 'object' ? result : obj;
    }
    

    测试用例:

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    let obj = _new(Person, 'xia', 20);
    console.log(obj); //{name: 'xia', age: 20}
    

    .

    构造函数上的方法

    1. 在构造函数上直接定义方法(不共享)

    function Person() {
        this.say = function () {
            console.log('hello');
        }
    }
    let p1 = new Person();
    let p2 = new Person();
    p1.say(); // hello
    p2.say(); // hello
    console.log(p1.say === p2.say); // false
    

    很明显,p1 和 p2 指向的不是一个地方。 所以 在构造函数上通过this来添加方法的方式来生成实例,每次生成实例,都是新开辟一个内存空间存方法。这样会导致内存的极大浪费,从而影响性能
    .

    2. 通过原型添加方法(共享)
    构造函数通过原型分配的函数,是所有对象共享的。

    function Person(name) {
        this.name = name;
    }
    Person.prototype.say = function () {
        console.log('hello ' + this.name);
    }
    let p1 = new Person('张三');
    let p2 = new Person('李四');
    p1.say(); // hello 张三
    p2.say(); // hello 李四
    console.log(p1.say === p2.say); // true
    

    所以我们经常 将公共属性定义到构造函数里,将公共方法放到原型对象上


    原型

    什么是原型?

    上面的Person.prototype就是原型,它是一个对象,我们也称它为原型对象。
    .

    原型的作用是什么?

    原型的作用,就是共享方法。
    我们通过 Person.prototype.say 可以共享方法,不会反复开辟存储空间。
    .

    原型中this的指向是什么?

    指向实例化对象p1、p2


    函数对象

    1. __proto__:所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型)
    2. prototype:所有函数拥有 prototype 属性(显式原型)(仅限函数)
    3. constructor:所有 prototype 都有一个 constructor 属性指向关联的构造函数

    当我们声明一个function关键字的方法时,会为这个方法添加一个prototype属性,指向默认的原型对象,并且此prototype的constructor属性也指向方法对象。此二个属性会在创建对象时被对象的属性引用。

    function Hello() {}; // 构造函数
    var h = new Hello();  // 实例化对象
    
    // 构造函数有个prototype属性
    console.log(Hello.prototype); // Object {}  原型对象
    // 构造函数的prototype属性有个constructor属性,指向构造函数本身
    console.log(Hello.prototype.constructor === Hello); // true
    
    
    // 实例化对象没有prototype属性
    console.log(h.prototype); // undefined
    // 实例化对象的constructor属性指向构造函数本身
    console.log(h.constructor === Hello); // true
    // 即
    console.log(h.constructor === Hello.prototype.constructor); // true 
    
    
    console.log(h.__proto__ === Hello.prototype); // true  
    // 即
    console.log(h.__proto__ === h.constructor.prototype); //true
    // 即
    console.log(Hello.prototype === h.constructor.prototype); //true
    

    在这里插入图片描述
    在这里插入图片描述


    constructor

    每个对象都可以通过对象.constructor指向创建该对象的构造函数

    function Person() {};
    var person1 = new Person();
    var person2 = new Person();
    
    person1.constructor === Person; // true
    Person.constructor === Function; // true
    Function.constructor === Function; // true
    

    在这里插入图片描述

    1. person1与person2是Person对象的实例,他们的constructor指向创建它们的构造函数,即Person函数;
    2. Person是函数,但同时也是Function实例对象,它的constructor指向创建它的构造函数,即Function函数;
    3. Function函数,它是JS的内置对象,它的构造函数是它自身,所以内部constructor属性指向自己。

    所以constructor属性其实就是一个拿来保存自己构造函数引用的属性,没有其他特殊的地方。


    prototype

    // 下面是给person1和person2实例添加了同一个效果的方法sayHello
    person1.sayHello = function() {
        console.log('Hello!')
    }
    person2.sayHello = function() {
        console.log('Hello!')
    }
    console.log(person1.sayHello === person2.sayHello) // false,它们不是同一个方法,各自占有内存
    

    在这里插入图片描述
    当你去对比这两个方法的时候,你会发现它们只是效果相同、名字相同,本质上却是各自都占用了部分内存的不同方法。这时候就出问题了,如果这时候有千千万万个实例(夸张)要这样效果同样的方法,那内存岂不是要炸。这时,prototype就出现解决问题了。

    当需要为大量实例添加相同效果的方法时,可以将它们存放在prototype对象中,并将该prototype对象放在这些实例的构造函数上,达到共享、公用的效果。代码如下:

    Person.prototype.sayHello = function() {
        console.log('Hello!')
    }
    console.log(person1.sayHello === person2.sayHello) // true,同一个方法
    

    在这里插入图片描述
    prototype对象用于放某同一类型实例的共享属性和方法,实质上是为了内存着想。

    讲到这里,你需要知道的是,所有函数本身是Function函数的实例对象,所以Function函数中同样会有一个prototype对象放它自己实例对象的共享属性和方法。所以上面的图示是不完整的,应改成下图:
    在这里插入图片描述


    _proto _

    在这里插入图片描述


    在这里插入图片描述

    /*1、字面量方式*/
    var a = {};
    console.log(a.constructor === Object); // true (即构造器Object)
    console.log(a.__proto__ === a.constructor.prototype); // true
    console.log(a.__proto__ === Object.prototype); // true
    
    /*2、构造器方式*/
    var A = function (){}; 
    var a = new A();
    console.log(a.constructor === A); // true(即构造器function A)
    console.log(a.__proto__ === a.constructor.prototype); // true
    
    /*3、Object.create()方式*/
    var a1 = {a:1} 
    var a2 = Object.create(a1);
    console.log(a2.constructor === Object); // true  (即构造器Object)
    console.log(a2.__proto__ === a1); // true 
    console.log(a2.__proto__ === a2.constructor.prototype); //false(此处即为图1中的例外情况)
    
    

    原型链

    在这里插入图片描述

    // 由__proto__组成的原型链
    a.__proto__ === A.prototype; // true
    A.prototype.__proto__ == Object.prototype; // true
    Object.prototype.__proto__ === null; // true
    

    对象之所以可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在

    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.say = function () {
        console.log('hello', this.name);
    };
    let p1 = new Person('张三', 18);
    console.log(p1.__proto__ === Person.prototype); // true
    console.log(p1.__proto__.say === Person.prototype.say); // true
    console.log(p1.__proto__.say === p1.say); // true
    console.log(p1.say === Person.prototype.say); // true
    

    终极图

    这个图要是看懂了,原型与原型链就基本摸清了。?
    在这里插入图片描述

    展开全文
  • JS原型原型链是什么?

    万次阅读 多人点赞 2018-10-06 11:00:52
    原型链"(prototype chain)模式,来实现继承。 Brendan Eich设计javascript之初是为了实现网页与浏览器之间交互的一种简单的脚本语言 如果真的是一种简易的脚本语言,其实不需要有"继承"机

    Javascript语言的继承机制一直很难被人理解。

    它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instance)的区分,全靠一种很奇特的"原型链"(prototype chain)模式,来实现继承。

    Brendan Eich设计javascript之初是为了实现网页与浏览器之间交互的一种简单的脚本语言

    如果真的是一种简易的脚本语言,其实不需要有"继承"机制。但是,Javascript里面都是对象,必须有一种机制,将所有对象联系起来。所以,Brendan Eich最后还是设计了"继承"。


     

    背景介绍

    1.构造函数

    构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象。每个构造函数都有prototype(原型)属性

    2.原型模式

    每个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含特定类型的所有实例共享的属性和方法,即这个原型对象是用来给实例共享属性和方法的。
    而每个实例内部都有一个指向原型对象的指针。

    image.png

    原型链

    每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含指向原型对象内部的指针。我们让原型对象的实例(1)等于另一个原型对象(2),
    此时原型对象(2)将包含一个指向原型对象(1)的指针,
    再让原型对象(2)的实例等于原型对象(3),如此层层递进就构成了实例和原型的链条,这就是原型链的概念


     

    构造函数

    构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象。 即为对象变量赋初始值。每个构造函数的实例都将共享构造函数的初始值。 构造函数的出现是为了解决使用Object构造函数和字面量表示法不方便创建大量重复对象的问题。

    传统创建对象实例的方法

    
       var person={
           name:'张女士',
           age:'80',
           gender:'女'
       };
     console.log(person)
    

    注:这个方法如果用于创建大量相同属性和方法的对象时,会产生大量重复代码

    构造函数的方法

    
         //构造函数方法创建对象实例
         function Person(name,age,gender) {
         this.name=name;
         this.age=age;
         this.gender=gender;
         this.say=function () {
         alert(this.name)
               }
         }
        var person1=new Person('钟女士',80,'女');
        var person2=new Person('张女士',80,'女');
        console.log(person2)
        console.log(person1)
    

    原型模式

    使用构造函数的问题是,每个方法都要在每个实例上重新创建一遍,即在构造函数的不同实例上的同名函数是不相等的。而我们创建每个构造函数都有一个prototype(原型)属性,这个属性是个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法,我们使用这个原型对象来共享实例的属性和方法的模式就叫原型模式

    
      //原型模式创建对象
    function Person(){
     }
    Person.prototype.name='钟女士';
    Person.prototype.age=80;
    Person.prototype.gender='女';
    var person1= new Person();
    console.log(person1)
    //简写原型模式
    Person.prototype={
       constructor:Person
       name:'钟女士',
       age:80,
       gender:'女'
     }
    

    注:每个原型对象都有constructor属性,由于简写模式重写了默认的prototype对象,所以constructor也会被重新定义,不再指向他的构造函数,所以可以自己写一个constructor属性指向他的构造函数

    原型链

    每个构造函数都有原型对象,每个构造函数实例都包含一个指向原型对象的内部指针(proto),如果我们让第一个构造函数的原型对象等于第二个构造函数的实例,结果第一个构造函数的原型对象将包含一个指向第二个原型对象的指针,再然第三个原型对象等于第一个构造函数的实例,这样第三个原型对象也将包含指向第一个原型对象的指针,以此类推,就够成了实例于原型的链条,这就是原型链的基本概念

    
    function One(){
     }
     function Two(){
     }
     function Three(){
     }
     Two.prototype=new One();
     Three.prototype=new Two();
     var three=new Three();
     console.log(three);
     console.log(three.__proto__===Three.prototype) //true
     console.log(three.__proto__.__proto__===Two.prototype) //true
     console.log(three.__proto__.__proto__.__proto__===One.prototype)  //true
     console.log(three.__proto__.__proto__.__proto__.__proto__===Object.prototype)  //true
    

     

    在对象实例中,访问对象原型的方法

    • 1、使用proto属性
      此属性是浏览器支持的一个属性,并不是ECMAScript里的属性

    • 2.Object.getPrototypeOf

    • 3.使用constructor.prototype的方法
      对于不支持proto的浏览器,可以使用constructor,访问到对象的构造函数,在用prototype访问到原型

     

    使用原型链解释ANUGLAR作用域

    在开发过程中,我们可能会出现控制器的嵌套,看下面这段代码:

        <div ng-controller="OuterCtrl">
            <span>{{a}}</span>
             <div ng-controller="InnerCtrl">
                <span>{{a}}</span>
             </div>
         </div>
        <script>
        function OuterCtrl($scope) {
        $scope.a = 1;
        }
        function InnerCtrl($scope) {
        }
        </script>
    

    我们可以看到界面显示了两个1,而我们只在OuterCtrl的作用域里定义了a变量,但界面给我们的结果是,两个a都有值,现在自控制器里的a是从父控制器里继承过来的

    我们可以父子级的作用域看成两个原型对象,其中一个原型对象继承另一个原型对象的实例

    
    function Outer() {
        this.a = 1;
    }
    
    function Inner() {
    }
    
    var outer = new Outer();
    Inner.prototype=new Outer();
    var inner = new Inner();
    console.log(outer.a)
    console.log(inner.a)
    

    Angular的实现机制其实也就是把这两个控制器中的$scope作了关联,外层的作用域实例成为了内层作用域的原型。

    既然作用域是通过原型来继承的,自然也就可以推论出一些特征来。比如说这段代码,点击按钮的结果是什么?

    <div ng-controller="OuterCtrl">
        <span>{{a}}</span>
        <div ng-controller="InnerCtrl">
            <span>{{a}}</span>
            <button ng-click="a=a+1">a++</button>
        </div>
    </div>
    <script>
    function OuterCtrl($scope) {
        $scope.a = 1;
    }
    
    function InnerCtrl($scope) {
    }
    </script>
    

    点了按钮之后,两个a不一致了,里面的变了,外面的没变,这是为什么?

    
    function Outer() {
        this.a = 1;
    }
    
    function Inner() {
    }
    
    var outer = new Outer();
    Inner.prototype=new Outer();
    var inner = new Inner();
    inner.a = inner.a + 1;
    console.log(outer.a)
    console.log(inner.a)
    

    因为在原型链中,访问一个实例属性时,会在实例本身查找,如果找不到,则搜索实例的原型,如果再搜索不到,则继续沿着原型链往上查找。找到之后则会赋给该实例,所以inner上面就被赋值了一个新的a,outer里面的仍然保持原样,这也就导致了刚才看到的结果。

    上下级共享变量

    比如说,我们就是想上下级共享变量,不创建新的,该怎么办呢?

    
    function Outer() {
        this.data = {
            a: 1
        };
    }
    
    function Inner() {
    }
    
    var outer = new Outer();
    Inner.prototype = outer;
    
    var inner = new Inner();
    
    console.log(outer.data.a);
    console.log(inner.data.a);
    inner.data.a += 1;
    
    console.log(outer.data.a);
    console.log(inner.data.a);
    

    我们可以把a写在一个对象里,当inner找到对象data并赋值到自己身上时,其实是复制了对象的指针(参考高程第4章复制引用类型和基本类型的区别),我们对对象里的属性的改动都会反映到所有引用该对象的元素上。
    反映到AngularJs,我们可以这么写

    <div ng-controller="OuterCtrl">
        <span>{{data.a}}</span>
        <div ng-controller="InnerCtrl">
            <span>{{data.a}}</span>
            <button ng-click="data.a=data.a+1">increase a</button>
        </div>
    </div>
    <script>
    function OuterCtrl($scope) {
        $scope.data = {
            a: 1
        };
    }
    
    function InnerCtrl($scope) {
    }
    </script>
    

    这样点击按钮两个控制器的a都会+1

     

    展开全文
  • JS(原型原型链)

    万次阅读 多人点赞 2018-08-06 09:00:23
    JS(原型原型链) 题目1.如何准确判断一个变量是数组类型 使用 instanceof 方法 题目2.写一个原型链继承的例子 实例:封装 DOM 查询 定义构造函数 Elem,属性封装成 id    打印出所有的 html   将...

    (学习自慕课网《前端JavaScript 面试技巧》

    JS(原型和原型链)

    题目1.如何准确判断一个变量是数组类型

    使用 instanceof 方法

    题目2.写一个原型链继承的例子

    实例:封装 DOM 查询

    定义构造函数 Elem,属性封装成 id 

     

    打印出所有的 html

     

    将所有的 html 变为 hello imooc ,并且点击弹出 ‘clicked’

    链式操作

     

    题目3.描述 new 一个对象的过程

     

    1.创建一个新对象

    2.this 指向这个新对象

    3.执行代码,即对 this 赋值

    4.返回 this

     

    构造函数

    大写字母开头一般都是构造函数

    new 的过程:

    1.var f = new Foo('zhangsan',20)  将参数传进去,函数中的 this 会变成空对象

    2.this.name = name;this.age = age;this.class = 'class-1' 为赋值;return this 为实际的运行机制

    3.return 之后赋值给 f ,f 具备了 f.name = zhangsan、f.age = 20、f.class = 'class-1'

    4.继续执行到 f1 ,则 f1.name = lisi、f1.age = 22、f1.class = 'class-1'

     

    构造函数(扩展)

    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 判断一个函数是否是一个变量的构造函数   (判断一个变量是否为“数组”  变量 instanceof Array)

     

    原型规则

    1.所有的引用类型(数组、对象、函数)都具有对象特性,即可自由扩展属性(除了“null”)

    2.所有的引用类型(数组、对象、函数)都有一个 _proto_ 属性(隐式原型属性),属性值是一个普通的对象

    3.所有的函数,都有一个 prototype(显式原型)属性,属性值也是一个普通的对象

    4. 所有的引用类型(数组、对象、函数), _proto_ 属性值(隐式原型属性)指向它的构造函数的“prototype”属性值

     当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_(即它的构造函数的 prototype(显式原型))中寻找

    5.

    f.printName() 中 f 的(自身)属性是 name ,属性值是 zhangsan

    f.alertName() 中 f 的隐式原型正好指向 Foo 的显式原型 Foo.prototype, f 本身没有 alertName 的属性,会去其隐式原型中寻找,故执行f.alertName()时会执行Foo.prototype.alertName = function (),因为 Foo 扩展 function,故输出 zhangsan

    故通过对象的属性的形式来执行函数的时候,无论函数是自身的属性还是从原型中得到的属性, this 永远指向 f 自身,没有指向函数,故执行f.alertName()时,alert(this.name) 中的 this 就是 f 。

    6.循环对象自身的属性

     

    if (f.hasOwnProperty(item)) 中遍历 f 时,判断遍历中的 item,是否可以通过 hasOwnProperty 验证,通过则表明它是 f 自身的属性,未通过则表明 是 f 通过原型获得的属性

    四、原型链

     

    f.toString(),当这个对象没有这个属性的时候,去它自身的隐式原型中找,它自身的隐式原型就是它构造函数(Foo)的显式原型(Foo.prototype)但显式原型(Foo.prototype)中并没有 toString ;但显式原型(Foo.prototype)也是对象,也要在它的隐式原型中找,即在其构造函数 (Object )的显式原型中去找 toString. 故要在 f._proto_(隐式原型)的._proto_(隐式原型)中找,如图所示,故输出 null

     

    方框为 构造函数,圆框为 对象,特例:Object.prototype 的 隐式原型是 null (JS避免死循环)

     五、instanceof

     判断 引用类型 属于哪个 构造函数 的方法

     

    f instanceof FOO 的判断逻辑:f 是 Foo new出来的一个类型(正确)

    判断方式:f 的隐式原型(proto)一层一层往上,能否对应到 Foo.prototype(显式原型)

     试判断:f instance of Object  (正确)见上图

    展开全文
  • 深入javascript之原型原型

    万次阅读 多人点赞 2019-01-14 11:30:55
    原型原型链是js中的难点也是重点,明白了原型原型链会让我们在后面不管是学习还是工作都会更加高效,并且原型原型链会是面试中必不可少的话题。看完此篇文章一定会让你对原型原型链有深刻全面的了解。 深入...
  • 原型

    2020-07-10 18:27:13
    原型 1.定义:原型是 function 对象的一个属性,它定义了构造函数制造出的对象的公共祖 先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。 2.利用原型特点和概念,可以提取共有属性。 3....
  • 原型原型链】什么是原型原型

    万次阅读 多人点赞 2018-06-21 15:21:55
    一、原型 ①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象 ②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象 ③所有引用类型的__proto__属性指向它构造函数的...
  • 到底什么是JS原型

    万次阅读 多人点赞 2018-10-14 21:27:00
    话说在前头,去网上查询很多关于JS原型的解释的文章,其中有80%看了都会不知所云,大多数关于JS原型的解释的文章或者视频,都忽略了很多读者对一些专业名词、概念是不掌握的,或许你说的一句话,就可以绕晕读者,...
  • 一、什么是原型 原型是Javascript中的继承的基础,JavaScript的继承就是基于原型的继承。 1.1 函数的原型对象 ​ 在JavaScript中,我们创建一个函数A(就是声明一个函数), 那么浏览器就会在内存中创建一个对象B...
  • **瀑布模型,原型模型,增量模型,螺旋模型,喷泉模型**,在实际项目中,通常数个模型方法共同使用
  • Axure常见的几种原型

    万次阅读 2018-05-25 15:16:17
    Axure RP是一款专业的快速原型设计工具。Axure常见的几种绘制图线框图:绘制页面大概轮廓低保真原型:比线框图更加细化交互说明/流程图:描述各个页面的各个功能点的流程关系,用线条把网页的触发点与出发后的页面...
  • 原型原型链的常见面试题

    千次阅读 2017-10-27 09:12:21
    //测试题1 var A=function(){} A.prototype.n=1 var b=new A() A.prototype={ n:2, m:3 } var c=new A() console.log(b.n,b.m,c.n,c.m)//1,undefined,2,3 //测试题2 ...Object.prototype
  • 交互原型案例Axure50套

    万次阅读 2019-04-03 09:47:54
    原型下载链接:https://pan.baidu.com/s/1cu5cfebWMSeacEou-Lg6sA 提取码:d0i4 想了解更多Axure资讯,赶快下方扫码加入【Axure修炼手册】微信公众号吧!!! ...
  • axure后台管理系统原型rp

    万次阅读 多人点赞 2018-08-02 15:20:03
    https://download.csdn.net/download/ymmygtl/10579255
  • 我们为什么不画高保真原型

    万次阅读 2018-04-21 23:11:55
    今天给大家分享一下,修真院官网PM任务5,深刻思考其中的知识点——我们为什么不画高保真原型图,希望能够给大家带来一些收获。目录1.原型图分类2.为什么我们不画高保真原型3.高保真原型的应用场景4.更多讨论5.参考...
  • 函数原型和函数声明的区别

    万次阅读 2018-07-04 19:22:24
    函数原型:指明函数的名字,返回的类型,有几个参数,这几个参数是什么类型,不需要函数体,也不需要形式参数的名字,其中用分号作为原型的结束符。例如:int fun( int );第一个int指明返回的类型,第二个int指明...
  • Axure 元件库-原型

    万次阅读 热门讨论 2019-04-19 17:40:58
    元件名称: 1、Axure交互原型设计指南 .rp 2、PC和移动原型常用元件.rp 3、后台模板.rp 4、全局说明.rp https://pan.baidu.com/s/1vmac_08MZAKj6qsdjwIZlg 提取码:5n0z ...
  • 软件需求工程 课堂笔记8

    万次阅读 2017-10-16 18:59:25
    原型原型原型原型系统通常被构造为不完整的系统,以在将来进行改进、补充或者替代。使用原型法获取需求原型法的使用要点 坚决抛弃抛弃式原型 控制原型成本 善用故事板原型 控制原型法风险 观察和文档审查观察的...
  • 5款Windows 界面原型设计工具

    万次阅读 2014-02-25 20:52:07
    界面原型图绘制工具 Pencil Pencil 是一款开源的原型图绘制工具,手绘风格的,就像自己在纸上画的那样。Pencil 还可以用来绘制各种架构图和流程图,同时还提供 Firefox 的插件。   
  • 我对js原型原型链的理解

    万次阅读 多人点赞 2020-08-11 17:15:38
    我们知道在js中,万物皆对象,对象可以说是重中之重了。...原型的出现就是为了解决这个问题。 在js中每个对象都有一个与它关联的对象,叫做原型对象。每一次获取对象属性都是一次查询过程,当在对象...
1 2 3 4 5 ... 20
收藏数 574,245
精华内容 229,698
关键字:

原型