那么什么是this,new,bind,call,apply呢?这些你都用过吗?掌握这些内容都是基础中的基础了。如果你不了解,那还不赶快去复习复习,上网查阅资料啥的!
通过call,apply,bind可以改变this的指向,this指向一般指向它的调用者,默认挂载在window对象下。es6中的箭头函数中,this指向创建者,并非调用者。
const func = function () {
console.log(this);
const func2 = function () {
console.log(this);
};
func2(); //Window
};
func(); //Window
'use strict'
const func = function () {
console.log(this);
const func2 = function () {
console.log(this);
};
func2(); //undefined
};
func(); //undefined
var a = 2
var obj = {
a: 4,
foo:() => {
console.log(this.a)
function func() {
this.a = 7
console.log(this.a)
}
func.prototype.a = 5
return func
}
}
var bar = obj.foo()
// 浏览器中输出: 2
bar()
// 浏览器中输出: 7
new bar()
// 浏览器中输出: 7
一般函数方法中使用this指向全局对象:
function test(){
this.x = 1
console.log(this.x)
}
test()
// 1
作为构造函数调用,this指向new实例化的对象:
function test(){
this.x = 1
}
var o = new test()
alert(o.x)
// 1
第一,this的学习,需要掌握哪些呢?this最重要的就是其指向的类型,那么在JavaScript中应该如何确定this的指向呢?
this是在函数被调用时确定的,它的指向完全取决于函数调用的地方,而不是它被声明的地方。(除了箭头函数)记住一点:this始终指向调用它的对象,对象中的方法中的this,指向调用它的对象。
var obj = {
a: 1,
b: {
a: 2,
func: function() {
console.log(this.a); // 输出结果为2
console.log(this); // 输出结果是b对象
}
}
}
// 调用
obj.b.func();
var obj = {
a: 1,
b: {
func: function() {
console.log(this.a); // undefind
console.log(this); // b对象
}
}
}
// 调用
obj.b.fun();
改变调用方法,不直接调用:
var obj = {
a: 1,
b: {
a: 2,
func: function() {
console.log(this.a); // undefined 若在对象obj外定义a,则输出的就是其在外定义的值
console.log(this); // window
}
}
}
var j = obj.b.func;
// 只是将b对象下的方法赋值给j,并没有调用
j();
// 调用,绑定的对象是window,并非b对象直接调用
在绝大多数情况下,函数的调用方式决定了this的值,this不能在执行期间被赋值,并且在每次函数被调用时this的值也可能会不同。this指向的对象称为函数的上下文对象context,this的指向取决于函数被调用的方式。
function foo() {
console.log(this);
}
那么我来问你?this指向哪里?哈哈哈,应该时不知道吧,因为谁调用指向谁,函数都没被调用,确实不知道指向。
function foo() {
console.log(this);
}
// window全局对象
> undefined
// obj对象
var obj = {
foo: foo
}
obj.foo();
> {foo:f}
直接通过函数名来调用函数,this指向全局变量window,通过对象,函数名调用函数,this指向该对象。当一个函数被调用的时候,会创建一个执行的上下文,它包含函数在哪里被调用,函数的调用方式,传入的参数等信息。
this的使用场景:
作为构造函数被new调用,作为对象的方法使用,作为函数直接调用,被call,apply,bind调用,箭头函数中的this。
基础:函数内部this指向问题:
var myObj = {
foo: "bar",
func: function() {
var self = this;
console.log(this.foo);
console.log(self.foo);
(function() {
console.log(this.foo);
console.log(self.foo);
}());
}
}
myObj.func();
结果:
bar
bar
undefined
bar
在对象方法中调用时:
var location = {
x: 0,
y: 0,
move: function(x,y) {
this.x = this.x + x;
this.y = this.y + y;
console.log(this.x); // 1
console.log(this.y); // 1
}
};
location.move(1,1)
// this绑定到当前对象,即为location对象
作为函数调用时:
function func(x) {
this.x = x;
}
func(2);
// 函数被调用时,this绑定的时全局对象window,相当于直接声明了一个全局变量x
console.log(x);
// x已经成为一个值为5的全局隐式变量
对象中this的指向问题:
var a = 1;
function printA() {
console.log(this.a);
}
var obj = {
a: 2,
foo: printA,
bar: function() {
printA();
}
}
obj.foo(); // 2
obj.bar(); // 1
var foo = obj.foo;
foo(); // 1
this的指向不是函数声明时绑定的,而是在函数运行过程中动态绑定的。
前端笔试:
function a(xx) {
this.x = xx;
return this;
}
var x = a(5);
var y = a(6);
console.log(x.x); //undefined
console.log(y.x); //6
基础:new绑定,显式绑定,隐式绑定,默认绑定,this绑定的优先级,箭头函数中的this。
箭头函数中的this是根据其声明的地方来决定this的,它是ES6中出现的知识点,箭头函数中的this,是无法通过call,apply,bind被修改的,且因箭头函数没有构造函数constructor,导致也不能用new调用,就不能作为构造函数了,否则会出现错误。
箭头函数不能arguments,super,this或new.target定义本地绑定。箭头函数中对arguments,super,this或new.target的任何引用都解析为当前所在词法作为域中的绑定,通常,这就是箭头函数所在函数作用域。
this在不同场景中的指向:
// 匿名函数中的this指向全局对象
var a = 2;
var func = {
a: 4,
fn: (function() {
console.log(this); // window
console.log(this.a); // 2
})()
}
// setInterval和setTimeout定时器中的this指向全局对象
var a = 2;
var oTimer = setInterval(function(){
var a = 3;
console.log(this.a); // 2
clearInterval(oTimer);
},100);
// eval中的this指向调用上下文中的this
(function() {
eval("console.log(this)"); // window
})();
function Foo() {
this.bar = function(){
eval("console.log(this)"); // Foo
}
}
var foo = new Foo();
foo.bar();
// apply 和 call中的this指向参数中的对象
var a = 2;
var foo = {
a: 20,
fu: function(){
console.log(this.a);
}
};
var bar = {
a: 200
}
foo.fu.apply(); // 2(若参数为空,默认指向全局对象)
foo.fu.apply(foo); // 20
foo.fu.apply(bar); // 200
this绑定的优先级:优先级:new绑定 > 显示绑定 > 隐式绑定 > 默认绑定
new绑定:函数中有new的调用,this绑定的是新创建的对象 显示绑定:函数中有bind,apply,call调用,this绑定的是指定的对象 隐式绑定:函数中是否在某个上下文对象调用,this绑定的是那个上下文对象 默认绑定:在严格模式下,就绑定到undefined,否则绑定到全局对象
new绑定:函数使用new调用时,this绑定的是新创建的构造函数的实例
function func() {
console.log(this)
}
var bar = new func()
// func实例,this就是bar
重点,创建一个新对象,构造函数的prototype被赋值给这个新对象的__proto__,将新对象赋给当前的this,执行构造函数,如果函数没有返回其他对象,那么new表达式中的函数会自动返回这个新对象。
显示绑定:call,apply,bind可以用来修改函数绑定的this
function fn (name, price){
this.name = name
this.price = price
}
function Food(category, name, price) {
fn.call(this, name, price) // call方式调用
// fn.apply(this, [name,price]) // apply方式调用
this.category = category
}
new Food('水果','苹果','6');
call和apply的区别:
call方法接受的是参数列表 apply方法接受的是参数数组
fu.call(this, arg1, arg2, ...) // call
fu.apply(this, [arg1,arg2, ...]) // apply
func.bind(thisArg[, arg1[, arg2[, ...]]])
// bind 用法
隐式绑定:函数是否在某个上下文对象中调用,如果是,this绑定的是那个上下文对象。
var a = 'hello5'
var obj = {
a: 'world',
foo: function() {
console.log(this.a)
}
}
obj.foo()
// 浏览器中输出: "world"
var a = 'hello555'
var obj = {
a: 'world555',
b:{
a:'Ch',
foo: function() {
console.log(this.a)
}
}
}
obj.b.foo()
// 浏览器中输出: "Ch"
默认绑定:
var a = 'hello'
function foo() {
var a = 'world'
console.log(this.a)
console.log(this)
}
foo()
// 相当于执行 window.foo()
// 浏览器中输出: "hello"
// 浏览器中输出: Window 对象
var a = 'hello'
var obj = {
a: 'world55',
foo: function() {
console.log(this.a)
}
}
var bar = obj.foo
bar()
// 浏览器中输出: "hello"
var a = 'hello'
var obj = {
a: 'world55',
foo: function() {
console.log(this.a)
}
}
function func(fn) {
fn()
}
func(obj.foo)
// 浏览器中输出: "hello"
new 是构造函数生成实例的命令, ES6为 new 命令引入了 new.target属性。这个属性用于确定构造函数是怎么调用的。在构造函数中, 如果一个构造函数不是通过 new操作符调用的, new.target会返回 undefined。
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。假设Test是一个构造函数,通常在创建对象的实例时,要使用new,eg:test = new Test() , 那么在调用new的时候,发生了什么呢?
1. 创建一个类的实例:创建一个空对象obj,然后把这个空对象的__proto__设置为Person.prototype(即构造函数的prototype);2. 初始化实例:构造函数Person被传入参数并调用,关键字this被设定指向该实例obj;3. 返回实例obj。
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。 ——(来自于MDN)new 创建的实例有以下 2 个特性:1、访问到构造函数里的属性;2、访问到原型里的属性
new 运算符 创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。比较好奇new运算符的原理,了解了下,分享给大家。自己写一个New()方法,
首先我们来看一下实例化一个对象做了浏览器做了什么事情,new的四步操作:1. 创建一个空对象2. 设置空对象的__proto__属性继承构造函数的prototype属性,也就是继承构造函数的原型对象上的公有属性和方法
理解new对象过程,需要提前了解原型及原型链的相关知识;我们都知道,JS当中创建对象使用的是原型设计模式,即使用new操作符调用构造函数,这里先看一个例子:
对于创建一个对象来说,更推荐使用字面量的方式创建对象(无论性能上还是可读性)。因为你使用 new Object() 的方式创建对象需要通过作用域链一层层找到 Object
上面的代码,我们首先创建了一个函数,如果是用面向对象的说法就是创建了一个Function类的实例,如果直接执行这个函数,那它就是一个普通的函数,如果用new执行,则这个函数被称为一个自定义的类。
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例,先看看 new 实现了哪些功能, 先来看一段代码:
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!