zoukankan      html  css  js  c++  java
  • 关于js构造函数中this的指向

    先来一道开胃菜:

    function person(name) {
                // 变量作用域为函数内部,外部无法访问,防止了变量名冲突和污染
                var name = '小明';
                this.name = name;
                this.sayName = function() {
                    console.log(name);
                }
                this.changeName = function(newName) {
                    name = newName;
                }
            }
            // 外部无法访问内部变量
            var a = new person();
            console.log(a.name)
    运行一下

    首先JS里没有类.
    构造函数是个函数,this指向的是个对象,this蒙上眼睛指也指不到构造函数去.
    构造函数的this指向创建的实例对象无疑. 要明白这一点,要先弄明白,用new操作符调用构造函数的时候都发生了什么.
    正好我有个答案是讲构造函数的, 我这里原样搬来:

    造函数其实和普通函数本质上并无区别,唯一的区别有两个:

    函数首字母大写,这个区别只是约定俗成的,便于区分。你实在要小写定义构造函数也完全没问题,所以这个区别可以忽略。

    构造函数的调用需要用new操作符,而普通函数的调用又分很多种,但是都不会用到new操作符。所以,构造函数和普通函数的区别就在这个new操作符里,现在让我们来好好研究一下这个new操作符。
    用new操作符创建对象时发生的事情:

    **第一步: 创建一个Object对象实例。
    第二步: 将构造函数的执行对象赋给新生成的这个实例。
    第三步: 执行构造函数中的代码
    第四步: 返回新生成的对象实例**

    注意:原本的构造函数是window对象的方法,如果不用new操作符而直接调用,那么构造函数的执行对象就 是window,即this指向了window。现在用new操作符后,this就指向了新生成的对象。理解这一步至关重要。
    执行构造函数中的代码,看代码:

    function Person(){
    this.name = "Tiny Colder";
    var age = 22;
    window.age = 22;
    }
    var p = new Person();
    alert(p.name)//Tiny Colder;
    alert(p.age)//undefined;
    alert(window.age)//22;

    当用new操作符创建对象时,先创建了一个对象实例,然后执行代码。所以还在纠结,什么时候构造函数定义的属性会继承给实例对象的,都可以这么来看:

    var p = new Object();
    p.name = "Tiny Colder";

    这是普通的创建对象,然后给对象添加属性的方法。如果每创建一个对象,都需要这么几行代码,无疑是糟糕的。这个需求就正好跟这一点对应:new操作符,自动执行构造函数里的代码。如此我们便可以省掉添加属性时重复冗余的代码。那么这些属性时如何添加到新生成的对象里的呢?

    第二个步骤里已经说了:将构造函数的执行对象赋给新生成的这个实例。再结合上一段里说的,自动执行构造函数里的this.name = "Tiny Colder";时,就相当于是执行p.name = "Tiny Colder";而构造函数里的
    var age = 22;语句,会执行但是对新生成的对象并无影响。window.age = 22;语句,会执行,且会给window对象添加一个属性。alert为证。

    或许到这里,你已经理解了new操作符的前三步了,重要的三步。但是这个函数是如何返回对象的呢?我们并没有看到有任何跟return相关的语句。这就是new操作符的最后一步:返回新生成的对象。
    如果被调用的函数没有显式的 return 表达式(仅限于返回对象),则隐式的会返回 this 对象 - 也就是新创建的对象。

    现在来看一下这个代码:

    function Person(){
    this.name = "Tiny Colder";
    return {};
    }
    var p = new Person();
    alert(p.name)//undefined;

    一个对象就这么被创建出来了。
    实际上,

    var p = new Person();

    var p = new Object();
    Person.apply(p);

    是一样的效果。

    简单的总结:

    显式的返回以下值:undefined, null, boolean, number等基础类型,并不会代替 new 式调用的默认行为。

    但显式返回以下值:{},[],RegExp, Date, Function,均会代替 new 调用的默认返回值 this.

    大家都看到了,后者,全都是 对象,是复杂类型。

    如果函数体是严格模式,则不会绑定 this 至全局对象,如:

    var a = function (){'use strict';this.b = 'b'return /111/g};
    a(); // 直接报错
    因为严格模式下,默认的 this 指向 undefined
  • 相关阅读:
    你现在的技能,是不是只剩下给别人点赞了?
    web编码(转)
    Android 官方文档:(二)应用清单 —— 2.26 <uses-permission>标签
    BackTrack5 (BT5)无线password破解教程之WPA/WPA2-PSK型无线password破解
    开源 java CMS
    EM算法原理
    OpenCV2马拉松第14圈——边缘检測(Sobel,prewitt,roberts)
    winzip15.0注冊码
    什么是积分墙?
    Bitmap工具类
  • 原文地址:https://www.cnblogs.com/jayfeng/p/12173439.html
Copyright © 2011-2022 走看看