JS构造函数、原型、原型属性区分、this指向、改变this指向

50 阅读2分钟
1. JS构造函数

JS构造函数首字母大写(不成文的规定), 普通函数一般首字母小写

// 普通(用它new不规范)
function fn1() {
    console.log('这是一个普通函数')
}

// 构造函数
function Person() {
// new
    // 内部会声明一个var this = {};
    // 函数体
    // return this;
    
    // 1.非严格模式下 this是window
    // 2.严格模式下 this是undefined
    // "use strict";
    // 3. new的时候就是当前函数的实例
    console.log(this.constructor === Person);;// new的时候都是true
    console.log(this.constructor === arguments.callee);// new的时候都是true
    console.log(this instanceof arguments.callee);// new的时候都是true

    // invoke执行函数体内的代码
    this.name = 'Green';
    return '调用的返回值';
}

构造函数可以和普通函数一样被调用

var invoke = Person();
console.log(invoke);// 调用的返回值

构造函数还可以创建一个实例

// 创建一个实例 做构造函数
var instance = new Person();
console.log(instance);

image.png

2. 原型:可以供所有实例访问
function Animal(name) {
    // this
    this.name = name;
    // V1:N个对象 N个相同方法赋值给N个属性
    this.eat = function () {
        console.log('哇呜哇呜..好吃')
     }
}

var an1 = new Animal('小红');
an1.eat(); //哇呜哇呜..好吃
console.log(an1.name) // 小红
var an2 = new Animal('张三'); 
an2.eat(); //哇呜哇呜..好吃
console.log(an2.name)// 张三

1) 隐式原型 实例.proto

2) 显示原型 构造函数.prototype

Animal.prototype.age = 123;

Animal.prototype.eat = function(){
    console.log(this.name,'正在哇呜哇呜..好吃')
}

console.log(Animal.prototype === an2.__proto__) //true
console.log(Animal.prototype === an1.__proto__) //true
console.log(an1.__proto__ === an2.__proto__) //true
3. 原型属性区分
var log = console.log;
function Animal(name) {
    this.name = name;
}
// 数据共享
Animal.prototype.age = 123;
var an1 = new Animal('小K');

1)通用属性判断 无法区分 是否原型属性 或者实例自身属性

log('name' in an1); // true
log('age' in an1);// true
  1. 遍历 可以获取到所有的 无法区分 是否原型属性 或者实例自身属性
for (var key in an1) {
    console.log(key, an1[key]);
}

image.png

3)hasOwnProperty() 非原型获取 判断是否属于自身属性

log(an1.hasOwnProperty('name')); // true
log(an1.hasOwnProperty('age')); // false

4)获取 key 获取value 【自身, 无法获取原型上的属性】

log(Object.keys(an1)); // [name]
log(Object.values(an1));
4. this指向 谁.调用的方法,this就代表谁
function fn(expressStr) {
    console.log('exp:', expressStr, 'this:', this);
}
var arr = [fn,2,3];
arr[0]('arr[0]'); //this指向arr, arr[0]可以理解为: arr.0 取到了函数(),所以this代表数组

image.png

var obj = { fn: fn };
obj.fn('obj.fn');//this指向obj

image.png

var obj3 = {
    fn: fn
}
var arrOfObj = [1, 2, 3, obj3]
arrOfObj[3].fn('arrOfObj[3]'); 

image.png

5. 改变this指向
var str = false;
function ffn(){
    console.log('this:',this,'arguments:',arguments);
}

1)apply 调用的时候,使用第一个参数作为this

ffn.apply(str,[6,5,8])

2)call 调用的时候,使用第一个参数作为this,与call的区别是后面传递参数格式不同

ffn.call(str,1,2,3)

apply和call都是临时改变this指向

3)bind 返回一个改变了this指向的函数,也可以提前传递参数(this指向永久改变)

var newFn = ffn.bind(str,97)
newFn(98,99)// 新的函数还可以继续传递参数
注意:箭头函数不能用apply、call或者bind改变this指向
var arrows = () => { console.log(this, '箭头函数this') }
arrows(); // window
arrows.call(str, 'xxxx'); // window(不可改)

image.png