this
//1. 设置一个全局变量name
var name = '全局的name属性';
//2.访问 name
console.log(name); // 全局的name属性
//3.定义一个函数
function fn(){
console.log(name); // 全局的name属性(根据作用域原理,进入全局找)
}
//4. 定义两个对象
var obj = {
name:"孙悟空",
sayHello:fn
}
var obj2 = {
name:"猪八戒",
sayHello:fn
}
/*
obj.sayHello === fn() === obj2.sayHello
obj.sayHello() //全局的name属性
obj2.sayHello() //全局的name属性
fn() //全局的name属性
三个调用的是同一个函数
*/
要求: (调用了同一个函数,但结果不同)
调用obj.sayHello() -----> 孙悟空
调用obj2.sayHello() -----> 猪八戒
调用 fn() -----> 全局的name属性
/*
在调用函数时,浏览器每次都会向函数中传递一个隐式的参数
--- 这个参数的名字就叫this,this指向的是一个对象
*/
function fn(){
// 浏览器向函数中传了一个this参数
console.log(this); // window
}
//fn(); 括号里没有传参数
fn(); ---> window{...}
obj.sayHello(); ---> {name:'孙悟空',sayHello:fn}
obj2.sayHello(); ---> {name:'猪八戒',sayHello:fn}
/*
1.当以函数的形式调用一个函数时,this是window
2.当以方法的形式调用一个函数时,this是调用方法的对象
*/
function fn(){
//当name改成this.name
console.log(this.name);
}
// 结果满足要求
fn(); //全局的name属性
obj.sayHello(); //孙悟空
obj2.sayHello(); //猪八戒
所以 this 是谁调用了他,this就是谁。
练习:
let name = "沙和尚";
let obj3 = {
name:"孙悟空",
sayHello:function(){
console.log(name);
}
};
// 调用结果是什么
obj3.sayHello();
/*
function 中寻找变量 name , 当 function 中没有 name 时,就往这个函数的上一层找,
而孙悟空的 name 是 obj 这个对象的属性,全称应该是 obj.name ,所以就到全局中去找 name ,
所以 obj3.sayHello(); 调用的结果是 沙和尚
*/
let name = "沙和尚";
let obj3 = {
name:"孙悟空",
sayHello:function(){
// 这时的结果才是孙悟空,输出的 this 的属性,而且这里 this 指向了 obj3,因为是 obj3 调用了它。
console.log(this.name);
}
};
obj3.sayHello();
工厂方法创建对象
// 1.创建一个函数
function fn(name,age,gender,address){ //5.设置参数
//2.创建一个对象
let obj = {};
//3.向对象中添加要的属性
obj.name = name; // 可直接写 name
obj.age = age; // 可直接写 age
obj.gender = gender; // 可直接写 gender
obj.address = address; // 可直接写 address
//4. 将对象作为返回值返回
return obj;
}
//6.调用函数
let per1 = fn("孙悟空",18,"男","花果山");
let per2 = fn("猪八戒",28,"男","高老庄");
let per3 = fn("沙和尚",38,"男","流沙河");
let per4 = fn("唐三藏",48,"男","长安城");
//7.输出
console.log(per1); // {name:"孙悟空",age:18,gender:"男",address:"花果山"}
console.log(per2); // {name:"猪八戒",age:28,gender:"男",address:"高老庄"}
console.log(per3); // {name:"沙和尚",age:38,gender:"男",address:"流沙河"}
console.log(per4); // {name:"唐三藏",age:48,gender:"男",address:"长安城"}
构造函数
构造函数就是专门用来创建对象的函数
构造函数的定义的方式和普通函数没有区别
唯一的不同点在于构造函数的名字首字母要大写(非强制)
构造函数和普通函数区别在于调用方式
一个函数直接调用,那么它就是一个普通函数
构造函数使用 new 关键字调用
function fn(){
}
fu(); // 普通函数调用
new fn(); // 构造函数调用
构造函数执行流程:
1.创建一个新的对象
function Fn(){
1.1// 函数中没有返回值
}
let per = new Fn(); 1.3// 1.1中没有返回值,1.2有新的对象就是 new 关键字完成的
console.log(per); 1.2// 输出时得到的是一个新的对象 fn {}
2.将新的对象设置为函数中的 this
function Fn(){
// 在构造函数中打印 this
console.log(this); // this 表示的就是新建的对象
// 直接往 this 中添加,就是往新的对象中添加
this.name = "孙悟空";
this.age = 18
}
let per = new Fn(); // per 创建了构造函数,所以 this 就是指 per
console.log(per); // Fn{name:"孙悟空", age: 18}
3.执行函数中的代码
4.将新创建的对象返回
function Fn(name){
this.name = name;
}
function Dog(name){
this.name = name;
}
let per = new Fn ("孙悟空");
let per2 = new Fn ("猪八戒");
let per3 = new Dog("大黄狗");
console.log(per); // Fn {name:"孙悟空"}
console.log(per2); // Fn {name:"猪八戒"}
console.log(per3); // Dog{name:"大黄狗"}
向类中添加方法:
//定义一个表示人类的类
function Person(name,age){
this.name = name;
this.age = age;
//添加一个方法
this.sayHello = function(){
console.log("大家好我是" + this.name);
}
}
// 创建一个实例
let per = new Person("孙悟空",18)
//调用
per.sayHello(); // 大家好我是孙悟空
/*
方法直接定义在构造函数中,构造函数每执行一次,创建一个新的函数对象中,
每一个对象都有不同的sayHello()方法,但是这些sayHello()方法的功能是一样的
而创建许多会占用大量的内存空间,实际可以共用一个。
*/
// 将 sayHello 定义为全局函数
// 缺点:污染全局的命名空间,在全局中可能被覆盖
function sayHello(){
console.log("大家好我是" + this.name);
}
function Person(name,age){
this.name = name;
this.age = age;
//将全局的 sayHello 方法赋值给它
this.sayHello = sayHello;
}
let per = new Person("孙悟空",18)
per.sayHello(); // 大家好我是孙悟空
函数中没有返回值调用区别
function fn(){
// 函数中没有返回值
}
//普通函数调用
let per = fn();
// fn 把返回值赋值给 per ,fn 函数中没有返回值, 所以 per 是 undefined
conso.log(per); // undefined
//构造函数调用
let per = new fn();
// 输出 new 创建的新对象
console.log(per); // fn {}
一个构造函数也称为是一个类,通过该构造函数创建的对象称为该类实例
function Fn(name){
this.name = name;
}
function Dog(name){
this.name = name;
}
// per1 和 per2 是 new Fn 创建出来的,所以 per1 和 per2 都是 Fn 的实例
// 因为这两个都是 Fn 这个类创建的
// 通过同一个类创建的对象,称为同一类对象
let per1 = new Fn ("孙悟空");
let per2 = new Fn ("猪八戒");
// Dog 则不是同类创建的
let per3 = new Dog("大黄狗");
instanceof 用来检查一个对象是否是一个类的实例
语法:
对象 instanceof 类(构造函数)
//per1 是不是 Fn 的实例
//如果是类的实例则返回 true 反之返回 false
console.log(per1 instanceof Fn) // true
console.log(per3 instanceof Fn) // false