关于 JS this

1. this 与 普通函数

普通函数 this 永远指向它的调用对象

var obj = {
a:10,
b:{
a:20,
fn:function(){
console.log(this.a);
}
}
}
obj.b.fn(); //=> 20

对象 b 调用 fn 函数 this.a 为 20。

var obj2 = {
a:10,
b:{
fn:function(){
console.log(this.a);
}
}
}
obj2.b.fn(); //=> undefined

对象 b 中无 a 字段, this.a 为 undefined。

var obj3 = {
a:10,
b:{
a:20,
fn:function(){
console.log(this);
console.log(this.a);
}
}
}
var j = obj3.b.fn;
j(); //=> window, undefined

这里直接获取里fn对象,没有通过对象去调用。非严格模式下,this 默认指向全局对象window。

var obj4 = {
a:10,
b:{
a:20,
fn:function(){
"use strict";
console.log(this);
console.log(this.a);
}
}
}
var g = obj4.b.fn;
g(); //=> undefined, TypeError: Cannot read property 'a' of undefined

而严格模式下, this 为 undefined。

2. this 与 bind、call、apply

function.bind(thisArg[, arg1[, arg2[, ...]]]) 最简单的用法是创建一个函数,不论怎么调用,这个函数都有同样的 this 值。

function.call(thisArg, arg1, arg2, ...)、function.apply(thisArg, [argsArray]) call、apply 的作用类似都是为调用函数指定this。

function fn() {
return this.user;
} console.log(fn.call({ user: "li" })); //=> li console.log(fn.apply({ user: "wang" })); //=> wang var bfn = fn.bind({ user: "gao" });
console.log(bfn()); //=> gao console.log(bfn.call({ user: "liu" })); //=> gao console.log(bfn.apply({ user: "liu" })); //=> gao console.log(bfn.bind({ user: "liu" })()); //=> gao var obj = { user: 'zhang', f: fn, g: bfn };
console.log(obj.f(), obj.g()); //=> zhang, gao

对 bind 产生的函数使用,再使用 call、apply、bind, 指向的 this 仍然是初次bind的值。

function list() {
return Array.prototype.slice.call(arguments);
}
console.log(list(1, 2, 3)); //=> [1, 2, 3] function list2(){
if(arguments){
arguments.__proto__.slice = Array.prototype.slice;
return arguments.slice();
}
}
console.log(list2(4, 5, 6)); //=> [4, 5, 6] var leading37List = list.bind(null, 37);
console.log(leading37List()); //=> [37]
console.log(leading37List(1, 2, 3)); //=> [37, 1, 2, 3]

在函数代码中,特殊对象 arguments 无需明确指出参数名,就能访问它们。arguments 自带 length 属性, Array.prototype.slice.call(arguments) 可以理解成 arguments.slice()

3. this 与 箭头函数

由于箭头函数不绑定this,它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值。

var obj = {
a: 10,
b: function () {
console.log(this.a, this)
},
c: () => console.log(this.a, this),
}
obj.b(); //=> 10, Object{...}
obj.c(); //=> undefined, window{...} obj.c.apply({ a: 'apply' }); //=> undefined, window{...}
obj.c.call({ a: 'call' }); //=> undefined, window{...}
obj.c.bind({ a: 'bind' })(); //=> undefined, window{...}

call() 、 apply() 、 bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响。

function fn() {
this.a = 20;
this.b = () => console.log(this.a, this);
}
console.log((new fn()).b()) //=> 20, fn {a: 20, b: ƒ}

箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。

var lam = (...r) => {
console.log(r);
}
lam(1,2,3); //=> Array : [1, 2, 3]

箭头函数没有arguments,取而代之用rest参数…解决。

var B = ()=>{
value:1;
}
var b = new B(); //=> TypeError: B is not a constructor

箭头函数作为匿名函数,没有构造函数,不能使用new。

4. this 与 return

如果返回值是 引用类型 对象,那么this指向的就是那个返回的对象;

如果返回值是 非引用类型 对象那么this还是指向函数的实例。

4.1 返回引用对象

function fn()
{
this.user = '123';
return {};
}
var a = new fn;
console.log(a.user); //=> undefined

4.2 返回function对象

function fn()
{
this.user = '123';
return function(){};
}
var a = new fn;
console.log(a.user); //=> undefined

4.3 返回数字,值对象

function fn()
{
this.user = '123';
return 123;
}
var a = new fn;
console.log(a.user); //=> 123

4.4 返回undefined

function fn()
{
this.user = '123';
return undefined;
}
var a = new fn;
console.log(a.user); //=> 123

4.5 返回null

function fn()
{
this.user = '123';
return null;
}
var a = new fn;
console.log(a.user); //=> 123

返回目录

关于 JS this的更多相关文章

  1. Vue.js 和 MVVM 小细节

    MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...

  2. js学习笔记:操作iframe

    iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. JS调用Android、Ios原生控件

    在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...

  5. jquery和Js的区别和基础操作

    jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...

  6. 利用snowfall.jquery.js实现爱心满屏飞

    小颖在上一篇一步一步教你用CSS画爱心中已经分享一种画爱心的方法,这次再分享一种方法用css画爱心,并利用snowfall.jquery.js实现爱心满屏飞的效果. 第一步: 利用伪元素before和 ...

  7. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  8. JS正则表达式常用总结

    正则表达式的创建 JS正则表达式的创建有两种方式: new RegExp() 和 直接字面量. //使用RegExp对象创建 var regObj = new RegExp("(^\\s+) ...

  9. 干货分享:让你分分钟学会 JS 闭包

    闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...

  10. JS核心系列:理解 new 的运行机制

    和其他高级语言一样 javascript 中也有 new 运算符,我们知道 new 运算符是用来实例化一个类,从而在内存中分配一个实例对象. 但在 javascript 中,万物皆对象,为什么还要通过 ...

随机推荐

  1. UML的使用

    软件工程项目这周要交一个设计文档,其中涉及UML图的画法,根据上课给的ppt做一个记录. 有关于UML的介绍在这里不再赘述,直接开整! UML的基本模型 当然必要的介绍必不可少,这里先介绍UML的基本 ...

  2. SDN-based Network Management Solution

    SDN-based Network Management Solution 摘要: 在此项目中,我们开发了一种网络管理应用程序,以监视和控制由支持OpenFlow的交换机和支持SNMP的设备组成的企业 ...

  3. [代码质量] Git统计本次提交新增代码行数,建议每个评审commit新增行数小于400行

    git log HEAD~1..HEAD --author="$(git config --get user.name)" --pretty=tformat: --numstat ...

  4. ubuntu16上部署confluence-6.14.5的迁移

    author:headsen chen date:  2019-10-18  15:02:06 notice :created  by  headsen chen himself and not al ...

  5. xadmin插件

    from django.http import HttpResponse from xadmin.plugins.actions import BaseActionView class test(Ba ...

  6. springMVC中controller的传参的几种案例

    1.springmvc的controller方法不指定method时,默认get/post都支持 //@RequestMapping(value="test") //@Reques ...

  7. Python分词、情感分析工具——SnowNLP

    本文内容主要参考GitHub:https://github.com/isnowfy/snownlp what's the SnowNLP SnowNLP是一个python写的类库,可以方便的处理中文文 ...

  8. Python - Django - 使用 Bootstrap 样式修改注册页

    reg2 函数: from django.shortcuts import render, HttpResponse from app01 import models def reg2(request ...

  9. .Net Core个人笔记

    目录 前言 IOC注册 三种生命周期 如何注册一个IOC服务 .Net Core部署IIS之后500错误 管道和中间件 示意图 管道方法 中间件 加日志观看 使用MVC MVC服务注入 MVC管道调用 ...

  10. 查看已安装dpkg包的poinst安装文件

    /var/lib/dpkg/info |grep printburn(软件名称) /var/lib/dpkg/info 文件都在这个目录下面poinst, preinst,prerm等