你不知道的 this 原理

本文探讨了JavaScript中的this机制,解释了为何同一个函数在不同环境下执行结果会不同。作者通过实例展示了函数引用与实际执行环境的关系,指出this是根据函数调用方式确定的。文章强调了this设计的目的是为了实现函数的复用,提高开发效率。并以公司董事长、部门主管和员工的比喻,生动地阐述了this指向的概念。
摘要由CSDN通过智能技术生成

大家好,我是十七,大家对 this 一定很熟悉吧, 那你知道为什么会有 this 机制嘛? 今天来说道说道~

var a = "a"
var obj = {
    a : "obj.a",
    fn : function () {
        console.log(this.a)
    }
}
var newFn = obj.fn

newFn()  // a
obj.fn()  // obj.a

明明是同样的函数,为什么执行结果会不一样呢?

我想你会说 this 指向不一样, 那么 this 指向为什么会不一样呢? 这就是今天讨论的重点哦!

对于 this 呢,我的理解就是当前函数执行的环境, 里面存放着许许多多的声明变量和方法。

这其实和 JavaScript 语言底层的数据存储方式有关,在JavaScript 中,字符串、数字 都是用原始值保存, 对象 、数组、函数都是用索引值来保存,这就是说当你声明一个函数,

你拿到这个函数只是拿到了他的引用值,而不是拿到了它本身。请看

 var fn1 = function(){
     console.log(a)
 }
 var fn2 = fn1
 fn1.toString = function(){
     console.log("tostring")
 }
 fn2.toString() // tostring

fn1修改 tostring 方法之后, fn2 也同样被修改。

回到上面 obj.fn() 的代码,也就是说,当你调用 obj.a 时,js 会首先找到 obj 这个对象的索引值, 然后再根据 fn属性,找到fn函数的索引值,然后再执行这个函数,

也就是说这个函数执行的时候,是 通过obj.fn 的索引值执行的, 那么自然 obj 就是 obj.fn 的执行环境,即 fn 的 this 是 obj。

如果在全局执行 fn ,那么就是 window 通过索引值找到的 fn ,那么这个函数执行的环境就是window,所以 this 指向的是 window。

打个比方啊,window 相当于公司董事长,obj 相当于部门主管,fn 就是一个普通的职工。就如董事长想做一件事,告诉了部门主管要做什么事,部门主管呢 就找到了员工,让员工去做相应工作,这时候员工做事按照谁的规则走呢,当然是主管了,因为是主管派给你的任务,这就和 obj 调用 fn 一样,fn 必须按照 obj 的环境来执行。在 window 环境执行相当于董事长直接找你来工作,那你的工作当然要按照董事长的要求来走,相当于在全局调用 fn,fn 的 this 指向当然是 window。

this 机制这样设计的原因呢我是这样理解的:

    官方希望能够提供一种机制,可以让相同的函数在不同的环境执行能够满足不同的需求,假如每个函数只能对一个环境使用,那么在多个环境你就需要重复写很多的函数,代码会变得非常繁琐。如果能够改变函数其内部的环境指向,那就可以实现函数的复用,极大提升开发体验。

以上是我的理解,有不对的地方还请大家多多指教。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
由于不知道您需要哪种操作系统的原理文件管理实验代码,所以我提供一个通用的实验代码,供参考: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_FILE_NAME 100 #define MAX_FILE_SIZE 1024 typedef struct file{ char name[MAX_FILE_NAME]; char content[MAX_FILE_SIZE]; int size; }File; typedef struct directory{ char name[MAX_FILE_NAME]; struct directory* parent; struct directory* subdirectories[100]; File* files[100]; int subdirectory_count; int file_count; }Directory; void create_directory(Directory* parent, char* name){ Directory* new_directory = (Directory*)malloc(sizeof(Directory)); new_directory->parent = parent; strcpy(new_directory->name, name); new_directory->subdirectory_count = 0; new_directory->file_count = 0; parent->subdirectories[parent->subdirectory_count++] = new_directory; } void create_file(Directory* directory, char* name, char* content, int size){ File* new_file = (File*)malloc(sizeof(File)); strcpy(new_file->name, name); strcpy(new_file->content, content); new_file->size = size; directory->files[directory->file_count++] = new_file; } Directory* change_directory(Directory* current_directory, char* name){ if(strcmp(name, "..") == 0){ if(current_directory->parent != NULL){ return current_directory->parent; } else{ printf("You are already at the root directory.\n"); return current_directory; } } else{ for(int i=0; i<current_directory->subdirectory_count; i++){ if(strcmp(current_directory->subdirectories[i]->name, name) == 0){ return current_directory->subdirectories[i]; } } printf("Directory not found.\n"); return current_directory; } } void list_directory_contents(Directory* directory){ printf("Directories:\n"); for(int i=0; i<directory->subdirectory_count; i++){ printf("%s\n", directory->subdirectories[i]->name); } printf("\nFiles:\n"); for(int i=0; i<directory->file_count; i++){ printf("%s (%d bytes)\n", directory->files[i]->name, directory->files[i]->size); } } void delete_directory(Directory* directory){ for(int i=0; i<directory->subdirectory_count; i++){ delete_directory(directory->subdirectories[i]); } for(int i=0; i<directory->file_count; i++){ free(directory->files[i]); } free(directory); } int main(){ Directory* root = (Directory*)malloc(sizeof(Directory)); strcpy(root->name, "root"); root->parent = NULL; root->subdirectory_count = 0; root->file_count = 0; Directory* current_directory = root; create_directory(root, "documents"); create_directory(root, "pictures"); char document_content[] = "This is the content of the document."; create_file(root->subdirectories[0], "document.txt", document_content, strlen(document_content)); char input[100]; char command[20]; char arg1[100]; char arg2[100]; while(1){ printf("\n%s> ", current_directory->name); fgets(input, 100, stdin); sscanf(input, "%s %s %s", command, arg1, arg2); if(strcmp(command, "cd") == 0){ current_directory = change_directory(current_directory, arg1); } else if(strcmp(command, "mkdir") == 0){ create_directory(current_directory, arg1); } else if(strcmp(command, "create") == 0){ char file_content[MAX_FILE_SIZE]; printf("Enter file content:\n"); fgets(file_content, MAX_FILE_SIZE, stdin); create_file(current_directory, arg1, file_content, strlen(file_content)); } else if(strcmp(command, "ls") == 0){ list_directory_contents(current_directory); } else if(strcmp(command, "exit") == 0){ delete_directory(root); break; } else{ printf("Invalid command.\n"); } } return 0; } ``` 这个实验代码是一个简单的命令行界面文件管理器,支持创建、删除、修改和查看文件及目录。在该代码中,一个文件夹对应一个 Directory 结构体,一个文件对应一个 File 结构体。可以根据需要进行修改和扩展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值