js 高程 this和原型透析

1. 考察this

1.1

var name = 'naruto';
function show() {
    console.log('this:', this.name);
}
var obj = {
    name: 'xiaowa'
    show: show
}

obj.show(); // this: xiaowa

当obj调用show()时,show的this被隐私绑定到调用它的obj上,所以在show里面可以拿到obj的name属性

var name = 'naruto';
function show() {
    console.log('this name:', this.name)
}
var obj = {
    name: 'xiaowa',
    show: function() {
        show();
    }
}
obj.show(); // this: naruto

// 或者
var name = 'naruto';
function show() {
    console.log('this name:', this.name)
}
var obj = {
    name: 'xiaowa',
    show: show
}
var newShow = obj.show;
newShow(); // this: naruto

虽然obj声明了show属性并定义一个function,但是执行的时候是在全局作用域中直接执行,show函数中的this执行window;

1.2

var name = 'naruto';
var obj1 = {
    name: 'xiaowa',
    show: function() {
        console.log('this name:', this.name)
    }
}
(0, obj1.show)(); // this name: xiaowa

其实还是obj调用show方法,this指向obj;(1,2,3, function(){console.log('我是最后一个执行')})() // 我是最后一个执行

1.3

var obj = {
    name: 'naruto',
    sub: function() {
        name: 'xiaowa',
        show: function() {
            console.log('this name:', this.name)
        }
    }
}
obj.sub.show(); // this name: xiaowa

这种情况的调用位置在sub对象里,在show被调用时,this指向sub;

1.4

var name = 'naruto';
var obj = {
    name: 'xiaowa',
    show: function() {
        this.name = 'func';
        console.log('this name:', this.name)
    }
}
var newObj = new obj.show(); // this name: func

newObj 是通过new构造出来的一个实例对象,这个新对象指向obj.show的原型

1.5

var name = 'naruto';
var obj = {
    name: 'xiaowa',
    show: function() {
        this.name = 'func';
        console.log('this name:', this.name);
    }
}
var newObj = new (obj.show.bind(obj))(); // this name: func

绑定优先级问题: new > 显示绑定(bind > call & apply) > 隐式绑定

1.6

var obj = {
    show: function() {
        console.log('this :', this)
    }
};
var elem = document.getElementById('create');
elem.addEventListener('click', obj.show); // 返回elem dom对象
elem.addEventListener('click', obj.show.bind(obj)); // obj
elem.addEventListener('click', function() {
    obj.show(); // obj
});

elem.addEventListener('click', obj.show); 点击elem监听click事件属于方法调用,其中的this指向DOM对象;
elem.addEventListener('click', obj.show.bind(obj)); bind强绑定到obj上;
elem.addEventListener('click', function() obj.show();});,this三板斧中,谁点谁就指向谁;

2. 作用域

2.1

var person = 1;
function showPerson() {
    var person = 2;
    console.log(person);
}
showPerson(); //2

函数作用域,在执行showPerson时,在自身作用域空间中定义了person,因为console为2;

2.2

var person = 1;
function showPerson() {
    console.log(person);
    var person = 2;
}
showPerson(); //undefined

主要考察变量提升,在函数作用域中,person变量会提升,在打印时已定义未赋值,为undefined;

2.3

var person = 1;
function showPerson() {
    console.log(person);
    var person = 2;
    function person() {};
}
showPerson(); // ƒ person() {}

函数提升优先于变量提升

2.4

var person = 1;
function showPerson() {
    console.log(person);
    function person() {};
    var person = 2;
}
showPerson(); // ƒ person() {}

还是提升优先级问题,同2.3

2.5

for(var i = 1; i < 10; i++) {
    console.log(i)
} // 1 2 3 4 5 6 7 8 9

for(var i = 1; i < 10; i++) {
    setTimeout(function() {
        console.log(i)
    })
} // 10 10 10 10 10 10 10 10 10
// 回调函数在循环结束后执行

for(var i = 1; i < 10; i++) {
    (function(i) {
         setTimeout(function() {
            console.log(i)
        })
    })(i)
} // 1 2 3 4 5 6 7 8 9
// 通过自执行函数创建的作用域,把i传入自执行函数的作用域中,每次IIFE都创建一个新的作用域,在每次循环时都有一个新的变量供我们访问

for(let i = 1; i < 10; i++) {
    setTimeout(function() {
        console.log(i)
    })
    
} // 1 2 3 4 5 6 7 8 9
// let 声明还会有一个特殊的行为。这个行为指出变量在循环过程中不止被声明一次,每次迭代都会声明。随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量。

3. 面向对象

3.1

function Person() {
    this.name = 1;
    return {}
}
var person = new Person();
console.log('name :', person.name) // naem : undefined

构造函数中return空对象,在person实例中获取name的属性为undefined

3.2

function Person() {
    this.name = 1;
}
Person.prototype = {
    show: function() {
        console.log('name is:', this.name);
    }
}
var person = new Person();
person.show(); // name is: 1

原型继承,在构造函数创建出来的对象里,会通过__proto__查找构造器中的原型, person.proto === Person.prototype

3.3

function Person() {
    this.name = 1;
}
Person.prototype = {
    name: 2,
    show: function() {
        console.log('name is:', this.name);
    }
}
var person = new Person();
person.show(); // name is: 1

Person.prototype.show = function() {
    console.log('new show')
}
person.show(); // new show

考察原型链,如果在实例中找到了则返回,如果没有找到就会在当前实例中的原型对象里查找; Person.prototype.show覆盖了上面原型对象中的show

3.4

function Person() {
    this.name = 1;
}
Person.prototype = {
    name: 2,
    show: function() {
        console.log('name is:', this.name);
    }
}
var person = new Person();
var person2 = new Person();
person.show = function() {
    console.log('new show');
}
person.show();// new show
person2.show(); // name is: 1

原型链

3.5

function Person() {
    this.name = 1;
}
Person.prototype = {
    name: 2,
    show: function() {
        console.log('name is:', this.name)
    }
}
Person.prototype.show();
(new Person()).show();

Person 原型对象中定义了name:2,在通过prototype获取name值为2;
new 方法创建新对象,调用show时,此时还是原型链查找

posted @ 2019-08-08 16:33  inaruto  阅读(139)  评论(0编辑  收藏  举报