zoukankan      html  css  js  c++  java
  • JavaScript

    用栗子说this

    Bug年年有,今年特别多
    对于JavaScript这么灵活的语言来说,少了this怎么活!

    function

    函数 this

    对于没有实例化的function,我们称之为函数,即没有用new关键字调用的函数,对它们来说,this一律指代全局。

    上栗子

    var position = "outer";               
    
    function test(){
        position = "inner";           
    }console.log(this.position);     // outer   test();console.log(this.position);     // inner原因:内部未用var声明发生“变量提升”,污染全局变量。

    构造函数 this

    对于被实例化的function,我们称之为构造函数,及使用new关键字调用的function,对于它们来说,this会被改变,指向实例。

    上栗子

    var name = 'person';               // 全局this赋上属性namefunction Person(name){    this.name = name;    this.say = function () {        console.log('My name is '+this.name);
        }    this.show = function () {        console.log(this);
        }
    }var william = new Person('william'); //通过new关键字创建实例,改变函数内部this指向console.log(this.name);          //personwilliam.say();                   //My name is williamwilliam.show();                  //Person {name: "william", say: ...注解:通过这个栗子,我们可以看出,通过创建构造函数的实例,使得this的指向改变,指向了实例本身。

    原型对象 this

    每一个函数对象在创建的时候,都会自动添加一个prototype属性,这个prototype其实是一个指针,指向这个函数的原型对象。
    
    你可以通过prototype指针给这个函数对象的原型对象添加属性,在实例化函数对象后,可以通过this来访问原型对象上的属性。

    上栗子

    function Person(){ console.log(this.name); } Person.prototype.name = "william"; //给原型对象上赋name属性

    var person = new Person(); // 通过this.name访问原型对象上的属性,打印 "william"

    这还不够,咱们为函数对象直接添加同名,而不在原型对象上添加

    function Person(){
    this.name = "Jack";

    console.log(this.name); }

    Person.prototype.name = "william";

    var person = new Person(); // 打印 "Jack"

    这里有一个值得注意的地方:

    当你构造函数中存在和原型对象同名属性方法时,原型对象中的属性或方法会被隐藏,你只会访问到构造函数中的属性或方法`

    Object.create this

    通过Object.create创建函数对象实例,而不使用new关键字,也就是说它不会去调用构造函数

    上栗子

    function Person(name){    
        this.name = name;               
        this.showName = function () {        
    console.log(this.name + ' in constructor'); } } //在构造函数中的属性和方法,均同名

    Person.prototype.name = "jack"; Person.prototype.showName = function () {
    console.log(this.name + ' in prototype'); }; //在原型对象中的属性和方法,均同名

    var william = new Person("william");v
    ar jack = Object.create(Person.prototype); william.showName(); // william in constructorjack.showName(); // jack in prototype注解: - 使用new关键字创造的实例调用了构造函数的属性和方法 - 使用Object.create创造的实例调用了原型对象的属性和方法

    原型链 this

    原型链用于实现继承,当没有找到需要属性或方法时,会顺着原型链向上继续寻找。

    上栗子

    function Father(){
    this.name = 'father'; } //可以看做"父类"Father.prototype.showName = function () {
    console.log(this.name); };function Son(){
    this.name = 'son'; } //可以看做"子类"

    Son.prototype = new Father(); //这步是关键!
    var mike = new Son(); mike.showName(); // son注解: - 首先要强调的是JavaScript中没有"父类","子类","继承"这样的东西,我们只是通过原型链来实现这样的设计模式。 - 通过这一步 Son.prototype = new Father(); 我们将"子类"的prototype指针指向了"父类"函数对象

    设计模式:继承

     为什么这样就能实现继承呢?
    
     首先要想明白为什么实例能访问构造函数的原型对象
    
     在JavaScript中,有一个内部的属性,在火狐,谷歌浏览器中,将这个内部属性暴露了出来,就是它 __proto__

    上栗子(浏览器中)

    mike.__proto__ // Father {name: "father", showName: function}    
    Son.prototype  //Father {name: "father", showName: function}
    
    mike.__proto__ === Son.prototype  // true通过这个内部属性,我们可以访问到实例的构造函数的原型对象

    再来一枚(浏览器中)

    mike.__proto__.__proto__      //Father {showName: function}
    Father.prototype              //Father {showName: function}
    
    mike.__proto__.__proto__ === Father.prototype  // true
    
    我们现在通过__proto__访问到了"父类"的原型对象!
    继承得以实现!

    补充一句:

    我们可以访问到Son的name属性的值,却访问不到Father的name属性的值,是因为
     - mike是Son的实例(实例能做什么...?)
     - Father中的name没有对外开放,可以看做是私有属性

    总结

    主要探讨了
    - function作为函数、构造函数、原型对象时,this的指代情况
    - 扩展了另一种实例化方式Object.create
    - 细说了原型链原理和实现,模拟了继承的设计模式

  • 相关阅读:
    JS window对象 Navigator对象 Navigator 对象包含有关浏览器的信息,通常用于检测浏览器与操作系统的版本。
    JS window对象 返回下一个浏览的页面 forward()方法,加载 history 列表中的下一个 URL。
    JS window对象 取消计时器clearTimeout() setTimeout()和clearTimeout()一起使用,停止计时器。 语法: clearTimeout(id_of_setT
    JS window对象 History 对象 history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能。语法: window.history.[属性|方法]
    JS window对象 返回前一个浏览的页面 back()方法,加载 history 列表中的前一个 URL。 语法: window.history.back();
    JS window对象 计时器setTimeout() setTimeout()计时器,在载入后延迟指定时间后,去执行一次表达式,仅执行一次。 语法: setTimeout(代码,延迟时间);
    JS window对象取消计时器clearInterval() clearInterval() 方法可取消由 setInterval() 设置的交互时间。
    ELK问题处理
    nginx 日志变量含义
    nginx ssl 更换问题
  • 原文地址:https://www.cnblogs.com/-ding/p/6022688.html
Copyright © 2011-2022 走看看