本文已参与『新人创作礼』活动,一起开启掘金创作之路
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
1. this
- 当前函数的
this是在被调用的时候才能确定的 - 如果当前的执行上下文处于调用栈的栈顶,这个时候变量对象变成了活动对象,THIS指针才能确定
1.1 全局对象
- 全局对象this指向本身
var a=1;//声明绑定变量对象,但在全局环境中,变量对象就是全局对象
this.b=2;//this绑定全局对象
c=3;//赋值操作 隐式绑定
1.1 用点调用
- 在一个函数上下文中,this由函数的调用者提供,由调用函数的方式来决定指向
- 如果是函数执行,如果前面有点,那么点前面是谁
this就是谁
let obj = {
getName(){
console.log(this);
}
};
obj.getName();
1.2 直接调用
- 如果没有,this就是window(严格模式下是undefined),自执行函数中的this一般都是window
- Strict_mode
let obj = {
getName(){
console.log(this);
}
};
let getName = obj.getName;
getName();
1.3 绑定事件
- 给元素绑定事件的时候,绑定的方法中的this一般是元素本身
container.addEventListener('click',function(){
console.log(this);
});
1.4 箭头函数
- 箭头函数没有自己的this
- 也没有prototype
- 也没有arguments
- 无法创建箭头函数的实例
let fn = () => {
console.log(this);
console.log(arguments);//Uncaught ReferenceError: arguments is not defined
}
console.log(fn.prototype);//undefined
fn();
new fn();//VM4416:8 Uncaught TypeError: fn is not a constructor
1.5 构造函数
- 构造函数中的THIS是当前类的实例,通过this添加的属性名和属性值都是给当前的实例添加的
- 如果构造函数没有形参,在调用的时候可以直接省去()
- 实例和实例比较是不相等的(因为存储空间地址不同)
- 构造函数中this添加的属性都是私有的
function fn(){
this.name = "小明",
this.age = 20,
this.sex = "男"
}
var f1 = new fn()
var f2 = new fn()
1.5.1 构造函数中的return
当return一个基本类型时,return不会发生作用,构造函数依旧返回一个实例对象。
function fn(){
this.name = "小明",
this.age = 20,
this.sex = "男"
return 'string'
}
var f1 = new fn()
当return一个引用类型时,return会覆盖创建实例,构造函数返回自己手写的引用类型值。
function fn(){
this.name = "小明",
this.age = 20,
this.sex = "男"
return { }
}
var f1 = new fn()
当只使用return时,return只会终止代码执行。依旧返回一个创建的实例
function fn(){
this.name = "小明",
this.age = 20,
this.sex = "男"
return
console.log('这里不会被执行')
}
var f1 = new fn()
构造函数一般不会写return 因为他默认会返回就是当前的实例**
1.6 call/apply/bind
- call/apply/bind可以改变函数中this的指向
- 第一个参数是改变this指向(非严格模式下,传递null/undefined指向也是window)
- call参数是依次传递,apply是以数组的方式传递
!function (proto) {
function getContext(context) {
context = context || window;
var type = typeof context;
if (['number', 'string', 'boolean', 'null'].includes(type)) {
context = new context.constructor(context);
}
return context;
}
function call(context, ...args) {
context = getContext(context);
context._fn = this;
let result = context._fn(...args);
delete context._fn;
return result;
}
function apply(context, args) {
context = getContext(context);
context._fn = this;
let result = context._fn(...args);
delete context._fn;
return result;
}
function bind(context, ...bindArgs) {
return (...args) => this.call(context, ...bindArgs, ...args);
}
proto.call = call;
proto.apply = apply;
proto.bind = bind;
}(Function.prototype)
1.7
- 默认绑定
- 隐式绑定
- 显式绑定
- new绑定
- new > 显示 > 隐式 > 默认
隐式 > 默认
function one() {
console.log(this)
}
var obj = {
name: "obj",
one
}
obj.one()
显示 > 隐式
function one() {
console.log(this)
}
var obj = {
name: "obj",
one: one.bind("hello")
}
obj.one()
new > 显示
function one() {
console.log(this)
}
var helloOne = one.bind("hello")
var obj = new helloOne();
console.log(obj);
2. 面向对象
- 对象为无序属性的集合,其属性可以包含基本值、对象和函数
- Inheritance_and_the_prototype_chain
2.1 原型链
2.1.1 一切皆对象
- 对象就是一些属性的集合
- 方法也是一种属性
- 一切(引用类型)都是对象,对象是属性的集合
- 函数和数组也是对象
- 为什么
typeof function='function'
2.1.1.1 typeof
- 检测数据类型
typeof返回的都是字符串 - 基本数据类型 number string boolean undefined symbol
- 引用类型 null {} [] /&$/ Date => object
console.log(typeof a); // undefined
console.log(typeof 1); // number
console.log(typeof 'zhufeng'); // string
console.log(typeof true); // boolean
console.log(typeof Symbol('a')); // symbol
console.log(typeof function () { }); //function
console.log(typeof [1, 2, 3]); //object
console.log(typeof { name: 'zhufeng' }); //object
console.log(typeof null); //object
console.log(typeof new Number(1)); //object
2.1.2 函数
- 对象是通过函数创建的
- 批量生产对象的函数
Object - 实现私有和公有属性的封装
let obj = new Object();
obj.name='zhufeng';
obj.age = 10;
2.1.3 隐式原型
2.1.3.1 proto
- 每个对象都有一个proto属性,指向创建该对象的函数的prototype
- Object.prototype
__proto__指向的是null
2.1.3.2 自定义函数的prototype
- 自定义函数的
prototype的proto指向的就是Object.prototype
2.1.3.3 自定义函数
- 自定义函数Foo.proto指向Function.prototype
- Function的prototype和proto都指向
Function.prototype
let add = new Function('a','b','return a+b');
console.log(add(1,2));
2.1.4 instanceof
- instanceof运算符的第一个参数是一个对象,第二个参数一般是一个函数
- instanceof的判断规则是: 沿着对象的
__proto__这条链来向上查找找,如果能找到函数的prototype则返回true,否则 返回false
2.2 批量创建对象
- 通过
new来调用一个函数,这个函数就成为了构造函数,构造函数里可以对例对象的私有属性赋值 - 每个函数会有一个
prototype属性,此原型对象上存放所有实例的公有方法 - 若new的构造函数自己返回引用值,则以自己返回的为主,否则 返回创建的实例
- create
function Person(name) {
this.name = name;
}
Person.prototype.getName = function () {
console.log(this.name);
}
let person = new Person('zhufeng');
person.getName();
Object.create = function (proto) {
function F() {}
F.prototype = proto;
return new F();
};
function _new(clazz, ...args) {
let _this = Object.create(clazz.prototype);
let result = clazz.call(_this, ...args);
if ((result != null && typeof result === 'object') || typeof result === 'function') {
return result;
}
return _this;
}
2.3 继承
class Father {
static staticFatherName = "FatherName"
static staticGetFatherName = function () {
console.log(Father.staticFatherName); // ?
}
constructor(public name) {
this.name = name;
}
getName() {
console.log(this.name); // ?
}
}
class Child extends Father {
static staticChildName = "ChildName"
static staticGetChildName = function () {
console.log(Child.staticChildName); // ?
}
constructor(public name, public age) {
super(name);
this.age = age;
}
getAge() {
console.log(this.age); // ?
}
}
let child = new Child('zhufeng', 10);
child.getName();
child.getAge();
Child.staticGetFatherName();
Child.staticGetChildName();
知道答案或者文章有遗漏地方的小伙伴可以在评论区评论哦~~