用栗子说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
- 细说了原型链原理和实现,模拟了继承的设计模式

JavaScript - this详解 (二)的更多相关文章

  1. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  2. JavaScript事件详解-Zepto的事件实现(二)【新增fastclick阅读笔记】

    正文 作者打字速度实在不咋地,源码部分就用图片代替了,都是截图,本文讲解的Zepto版本是1.2.0,在该版本中的event模块与1.1.6基本一致.此文的fastclick理解上在看过博客园各个大神 ...

  3. JavaScript事件详解-jQuery的事件实现(三)

    正文 本文所涉及到的jQuery版本是3.1.1,可以在压缩包中找到event模块.该篇算是阅读笔记,jQuery代码太长.... Dean Edward的addEvent.js 相对于zepto的e ...

  4. JavaScript正则表达式详解(一)正则表达式入门

    JavaScript正则表达式是很多JavaScript开发人员比较头疼的事情,也很多人不愿意学习,只是必要的时候上网查一下就可以啦~本文中详细的把JavaScript正则表达式的用法进行了列表,希望 ...

  5. [原创]JavaScript继承详解

    原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...

  6. javascript设计模式详解之命令模式

    每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某 ...

  7. javascript设计模式详解之策略模式

    接上篇命令模式来继续看下js设计模式中另一种常用的模式,策略模式.策略模式也是js开发中常用的一种实例,不要被这么略显深邃的名字给迷惑了.接下来我们慢慢看一下. 一.基本概念与使用场景: 基本概念:定 ...

  8. JavaScript事件详解-zepto的事件实现

    zepto的event 可以结合上一篇JavaScript事件详解-原生事件基础(一)综合考虑源码暂且不表,github里还有中文网站都能下到最新版的zepto.整个event模块不长,274行,我们 ...

  9. javascript 函数详解2 -- arguments

    今天我们接着上篇文章来继续javascript函数这个主题.今天要讲的是函数对像中一个很重要的属性--arguments. 相关阅读: javascript 函数详解1 -- 概述 javascrip ...

  10. .NET DLL 保护措施详解(二)关于性能的测试

    先说结果: 加了缓存的结果与C#原生代码差异不大了 我对三种方式进行了测试: 第一种,每次调用均动态编译 第二种,缓存编译好的对象 第三种,直接调用原生C#代码 .net dll保护系列 ------ ...

随机推荐

  1. 浅谈Java引用和Threadlocal的那些事

      这篇文章主要介绍了Java引用和Threadlocal的那些事,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 1 背景 某一天在某一个群里面的某个群友突然提出了一个问 ...

  2. Vue使用echarts

    Vue使用echarts 该示例使用 vue-cli 脚手架搭建 安装echarts依赖 npm install echarts -S 创建图表 全局引入 main.js // 引入echarts i ...

  3. oracle常用函数总结(二)

    之前也有写过“oracle常用函数总结(一)”,为了尽量找全常见oracle函数,笔者特意查找了相关资料来作为参考,下边给大家罗列出来,部分和之前有重复的,希望能帮到大家! 列举了31个函数和1个分组 ...

  4. UNITY中使用不安全代码的相关设置

    必须执行以下三个步骤 1,在工程属性中设置:属性-生成-允许不安全代码 2,在Assets目录下增加 smcs.rsp(若打包设置中使用了.net 2.0 subset)或 gmcs.rsp(若打包设 ...

  5. PHP 性能优化之 PHP-FPM

    简介: PHP-FPM 是一个 PHP FastCGI 管理器,一般 Nginx 上面跑 PHP 程序都会将 PHP 程序丢给 PHP-FPM 来解析.好了,就这样! PHP 5.4 开始集成了 PH ...

  6. .NET 等宽、等高、等比例、固定宽高生成缩略图 类

    #region 根据原图片生成等比缩略图 /// <summary> /// 根据源图片生成缩略图 /// </summary> /// <param name=&quo ...

  7. lucene4

    在lucene通过对应的API建立索引.在学习的过程中我们了解到lucene下面索引的建立与关系数据库有相似的地方. IndexReader.delete删除有两种删除的形式. 第三个改变Docume ...

  8. MYSQL 存储过程、函数、临时表、游标

    创建函数 因为我们平时经常需要创建不同日期的数据,以模拟的场景,覆盖更多的用例,所以这里写了一个返回随机日期的demo.大家可以自行扩展. DROP FUNCTION IF EXISTS milan_ ...

  9. ajax获取json数据为undefined--原因解析

    解决办法:var dataObj=eval("("+data+")");//转换为json对象 问题: 1. 碰到一个问题ajax成功获取json数据后,取值显 ...

  10. 从计算框架MapReduce看Hadoop1.0和2.0的区别

    一.1.0版本 主要由两部分组成:编程模型和运行时环境. 编程模型为用户提供易用的编程接口,用户只需编写串行程序实现函数来实现一个分布式程序,其他如节点间的通信.节点失效,数据切分等,则由运行时环境完 ...