this指向
- 执行上下文 是代码
执行时
的运行环境 - 作用域 是
变量和函数
的可访问性规则(静态
);全局、函数和块状
;内层可访问外层,外层不能访问内层 - 词法环境 是
实现作用域的引擎内部机制
(静态
)
执行上下文
├─ 变量环境 (VariableEnvironment)
├─ 词法环境 (LexicalEnvironment) → 作用域链
└─ this 绑定
- 执行上下文是代码
运行的临时环境
,每次函数调用新建。- 作用域是
变量访问的规则
,分全局/函数/块级
作用域,内层可访问外层,外层不能访问内层
- 词法作用域强调作用域
在代码书写时确定
,闭包
基于此实现。- 区别:作用域是规则,执行上下文是规则运行时的具体实例。
- 联系:
执行上下文中的作用域链基于词法作用域构建
,逐层向上查找变量闭包
的本质是函数保留了定义时的词法作用域
(即使外层函数已销毁)
new绑定>显式绑定>隐式绑定>默认绑定
javascript
function myNew(constructor,...args){
// 1.创建一个空对象
// 2. 将这个空对象的原型设置为构造函数的 prototype 属性
let obj =obj.create(constructor.Prototype);
// 3. 将构造函数的 this 绑定到这个新对象,并执行构造函数
let result=constructor.apply(obj,args);
// 4. 如果构造函数返回一个对象,则返回这个对象,否则返回新创建的对象
return typeof result ===`object`?result:obj;
}
call&apply:判断调用对象是否为函数(this)->判断context是否为对象
bind:判断调用对象是否为函数(this)->定义一个新函数(根据是否使用new关键字调用设置this)->设置函数原型->返回新函数
bind方法不熟
javascript
/* call函数 */
// 参数区别:call 方法接受一个参数列表,而 apply 方法接受一个包含多个参数的数组
// bind方法返回一个新函数,而 call 和 apply 方法会立即执行函数
/* Function.prototype.myCall = function (context, ...args) {
// 判断调用对象是否为函数,this!!!
if (typeof this !== 'function') {
throw new TypeError('Error');
}
// 判断context是否为空
context = context || window;
// 判断context是否为对象!!
if (typeof context !== 'object') {
context = new Object(context);
}
// 将调用函数作为 context 的一个属性
const fnSymbol = Symbol('fn');
context[fnSymbol] = this;
// 调用函数并传入参数
const result = context[fnSymbol](...args);
// 删除临时属性
delete context[fnSymbol];
// 返回结果
return result;
};
function greet(message) {
console.log(`${message}, ${this.name}`);
}
const person = { name: 'John' };
greet.myCall(person, 'Hello');
*/
/* apply函数 */
Function.prototype.myApply = function (context, args) {
// 判断调用对象是否为函数,this!!!
if (typeof this !== 'function') {
throw new TypeError('Error');
}
// 判断context是否为空
context = context || window;
// 判断context是否为对象
if (typeof context !== 'object') {
context = new Object(context);
}
// 将调用函数作为 context 的一个属性
const fnSymbol = Symbol('fn');
context[fnSymbol] = this;
// 调用函数并传入参数
const result = context[fnSymbol](...args);
// 删除临时属性
delete context[fnSymbol];
// 返回结果
return result;
}
//bind函数
Function.prototype.myBind = function (context = window, ...initialArgs) {
// 检查调用 myBind 的是否为函数
if (typeof this!== 'function') {
throw new TypeError('调用 myBind 的对象必须是函数');
}
// 保存调用 myBind 的原始函数
const originalFunction = this;
// 返回一个新函数
const boundFunction = function (...newArgs) {
// 判断是否使用 new 调用
//当一个函数使用 new 调用时, this 会指向新创建的实例对象,并且这个实例对象会继承自该函数的原型。
const isUsingNew = this instanceof boundFunction;
// 合并预设参数和新传入的参数
const allArgs = [...initialArgs, ...newArgs];
// 如果是使用 new 调用,this 指向新创建的实例
const thisValue = isUsingNew? this : context;
// 调用原始函数
return originalFunction.apply(thisValue, allArgs);
};
// 复制原函数的原型,确保 boundFunction 作为构造函数时,新实例能继承原函数的原型方法
if (originalFunction.prototype) {
boundFunction.prototype = Object.create(originalFunction.prototype);
}
return boundFunction;
};
//测试bind方法
function greet(message) {
console.log(`${message}, ${this.name}`);
}
const person = { name: 'John' };
const greetPerson = greet.myBind(person, 'Hello');
greetPerson(); // 输出: Hello, John
// 测试 new 调用
function Person(name) {
this.name = name;
}
const BoundPerson = Person.myBind(null);
const newPerson = new BoundPerson('Alice');
console.log(newPerson.name); // 输出: Alice