JavaScript从零开始学习第6天
一.对象的方法
在 JavaScript 中,对象的方法是对象中定义的函数。它们可以通过对象的属性来访问和调用。
每一个函数的调用,都有其所对应的对象的调用。
全局的所有变量和函数都是window对象的成员。
例如:
var person = {
name: "Alice",
age: 17,
eat: function () {
console.log(this)
}
}
var fn=person.eat;
fn();//输出window
这里我想表示的意思是任何的函数调用都会有所对应的对象,this就是指其所对应的对象。
二.this关键字
在 JavaScript 中,this 是一个特殊的关键字,它引用当前执行上下文中的对象。具体来说,this 的值取决于函数的调用方式。
1.全局作用域中的 this:
当在全局作用域中使用 this 关键字时,它将引用全局对象(浏览器中为 window,Node.js 中为 global)。
2.函数中的 this:
当函数作为对象的方法被调用时,this 将引用该对象。
任何函数运行一定有一个对象在调用,谁让这个函数运行的,这个函数内部的this关键字就代表它
例:
var name = "Rance";
const person = {
name: 'Alice',
say: function () {
console.log('my name is ' + this.name);
}
};
person.say(); // 输出 "my name is Alice"
var fn = person.say;
fn();// 输出 "my name is Rance"
this不看它是哪个函数的也不看它是哪个对象的,而看它的函数是哪个对象调用的。重点在于是谁调用的。
:例如
var fm = function (arg) {
console.log(this.age, arg.age)
}
var obj = {
age: 24,
makeMoney: function (arg) {
console.log(this.age, arg.age)
fm(this)
}
}
var age = 200
obj.makeMoney(this)//输出24 200 200 24
var fn = obj.makeMoney
fn(this)//输出200 200 200 200
这里this的混用。搞清楚每个this所代表的意思也就差不多了,剩下的便是多练。
函数得调用才可以运行,那么 obj.makeMoney(this)这里的this是指全局对象也就window然后被当作实参传入函数,调用该函数的对象是obj这个对象。然后根据函数的运行规则,形实函运来执行,this被赋值给了arg。makeMoney这个函数里面this是指obj这个对象,所以里面this.age指得是obj.age,arg.age也就是window.age。所以输出24 200,其实后面的逻辑也就是如此。有些看似比较难的问题,用简单的思维去想也不过如此,无非也就加量而已。
var person = {
age: 18,
getAge: function () {
return this.age;
}
};
var getAge = person.getAge
console.log(getAge())//输出undefined
三.this的劫持-call-apply-bind
在 JavaScript 中,我们可以使用 call()、apply() 和 bind() 来劫持 this 关键字,即显式地指定函数执行时的 this 值。
1.call() 方法:
call() 方法允许我们在调用函数时明确指定函数执行时的 this 值,并且可以传递多个参数给函数。
例如:
function.call(thisArg, arg1, arg2, ...)//语法模板
function say(age, gender) {
console.log('My name is ' + this.name + " Gender " + gender + "," + age + " years old");
}
var person = {
name: 'Rance'
};
say.call(person, 21, "male"); // 输出 "My name is Rance Gender male, 21 years old"
2.apply() 方法:
apply() 方法与 call() 方法类似,区别在于它接受一个参数数组而不是参数列表。
function.apply(thisArg, [argsArray])//语法模板
function say(age, gender) {
console.log('My name is ' + this.name + " Gender " + gender + "," + age + " years old");
}
var person = {
name: 'Rance'
};
say.apply(person, [21,"male"]); // 输出 "My name is Rance Gender male, 21 years old"
需要注意的是:在给 apply() 方法传递参数时,需要将所有参数放在一个数组中,而不是将它们作为独立的参数传递。
3.bind() 方法:
bind() 方法返回一个新的函数,该函数具有指定的 this 值和参数。与 call() 和 apply() 不同,bind() 方法不会立即调用函数,而是返回一个绑定了 this 值的新函数。
function.bind(thisArg, arg1, arg2, ...)//语法模板
var name = "1111"
var obj2 = { name: "jack" }
var obj3 = { name: "marry" }
var obj = {
name: "karen",
say: function () {
console.log(this.name)
}.bind(obj2)
}
var fn = obj.say
fn()//输出 jack
obj.say.call(obj3)//输出 jack
obj.say.apply(obj3)//输出 jack
fn.call(obj3)//输出 jack
obj.say()//输出 jack
bind() 方法是函数原型上的一个方法,它可以用于创建一个绑定了指定对象作为 this 值的新函数。bind() 方法接受一个参数,即要绑定的对象,然后返回一个新的函数。当调用这个新函数时,它的 this 值将是绑定的对象。
四.new关键字
在 JavaScript 中,new 关键字用于创建一个对象实例。它用于实例化一个由构造函数定义的类,并返回一个新的对象。
1.构造函数:
function Person(name, age) {
this.name = name;
this.age = age;
}
2.使用 new 关键字调用构造函数,并传递所需的参数:
var person1 = new Person('Alice', 21);
console.log(person1.name)//输出Alice
3.在构造函数内部,this 关键字指向新创建的对象实例
function Person(name, age) {
this.name = name;
this.age = age;
console.log(this); // 输出新创建的对象实例
}
注意:如果构造函数内部没有显式地返回一个对象,则 new 关键字会返回新创建的对象实例。如果构造函数内部有显式的返回语句,则返回的是返回语句指定的对象,而不是新的对象实例。
function Person(name, age) {
this.name = name;
this.age = age;
// 显式返回一个对象
return { message: 'This is not a person object' };
}
var person1 = new Person('Alice', 21);
console.log(person1); // 输出 { message: 'This is not a person object' }
在上面的示例中,构造函数 Person 返回了一个新的对象,而不是新的对象实例。因此,person1 的值将是返回的对象,而不是通过 new 关键字创建的对象实例。
五.原型(prototype)对象
在 JavaScript 中,每个对象都有一个原型(prototype),它是一个指向另一个对象的引用。原型对象是一个共享的对象,它包含了共享的属性和方法,可以被其他对象继承和访问。
function fn() {
this.name = "Rance"
}
fn.prototype.age = 21
var f1 = new fn()
console.log(f1.name)//输出Rance
console.log(f1.age)//输出21
console.log(f1.__proto__.age)//输出21
f1.__proto__.age = 25//相当于修改了公共区域的值
var f2 = new fn()
console.log(f2.age)//输出25
console.log(f1.age)//输出25
这里用到了__proto__这个属性来访问对象的原型。
通过 prototype 属性,我们可以为构造函数的所有实例对象添加共享的属性和方法。这样可以避免在每个实例对象上重复创建相同的属性和方法,提高代码的效率和可维护性。