第一题
var length = 10; function fn() { return this.length + 1; } var obj = { length: 5, test1: function() { return fn(); } }; obj.test2 = fn; console.log(obj.test1.call()); // 11 默认绑定 console.log(obj.test1()); // 11 默认绑定 console.log(obj.test2.call()); // 11 显示绑定,绑了个寂寞 console.log(obj.test2()); // 6 隐式绑定
第二题
window.number = 2; var obj = { number: 3, db1: (function(){ console.log(this); this.number *= 4; return function(){ console.log(this); this.number *= 5; } })() } var db1 = obj.db1; // IIFE window 8 db1(); // 40 window 默认绑定 obj.db1(); // 15 隐式绑定 obj console.log(obj.number); // 15 console.log(window.number); // 40
第三题 考this优先级
function foo(something){ this.a = something } var obj1 = { foo: foo } var obj2 = {} obj1.foo(2); // 隐式绑定 obj1.a = 2 console.log(obj1.a); // 2 obj1.foo.call(obj2, 3); // 显示绑定 obj2.a = 3 console.log(obj2.a); // 3 var bar = new obj1.foo(4) // new绑定 bar.a = 4 console.log(obj1.a); // 2 console.log(bar.a); // 4
第四题
var name = "window"; var person = { name: "person", sayName: function () { console.log(this.name); } }; function sayName() { var sss = person.sayName; sss(); // 默认绑定window person.sayName(); // 隐式绑定person (person.sayName)(); // 隐式绑定person (b = person.sayName)(); // 默认绑定window } sayName();
第五题
var name = 'window' var person1 = { name: 'person1', foo1: function () { console.log(this.name) }, foo2: () => console.log(this.name), foo3: function () { return function () { console.log(this.name) } }, foo4: function () { return () => { console.log(this.name) } } } var person2 = { name: 'person2' } person1.foo1(); // 隐式绑定 'person1' person1.foo1.call(person2); // 显示绑定 'person2' person1.foo2(); // 箭头函数绑定 'window' person1.foo2.call(person2);// 箭头函数绑定 'window' person1.foo3()(); // 默认绑定 window person1.foo3.call(person2)(); // 默认绑定 window person1.foo3().call(person2); // 显示绑定 'person2' person1.foo4()(); // 箭头函数绑定 'person1' person1.foo4.call(person2)();// 箭头函数绑定 'person2' person1.foo4().call(person2); // 箭头函数绑定 'person1'
第六题
var name = 'window' function Person (name) { this.name = name this.foo1 = function () { console.log(this.name) } this.foo2 = () => console.log(this.name) this.foo3 = function () { return function () { console.log(this.name) } } this.foo4 = function () { return () => { console.log(this.name) } } } var person1 = new Person('person1') var person2 = new Person('person2') person1.foo1() // 隐式绑定 person1 person1.foo1.call(person2) // 显示绑定 person2 person1.foo2() // 箭头函数绑定 person1 person1.foo2.call(person2) // 箭头函数绑定 person1 person1.foo3()() // 默认绑定 window person1.foo3.call(person2)() // 默认绑定window person1.foo3().call(person2) // 显示绑定person2 person1.foo4()() // 箭头函数绑定 person1 person1.foo4.call(person2)() //箭头函数绑定 person2 person1.foo4().call(person2) //箭头函数绑定 person1
第七题
var name = 'window' function Person (name) { this.name = name this.obj = { name: 'obj', foo1: function () { return function () { console.log(this.name) } }, foo2: function () { return () => { console.log(this.name) } } } } var person1 = new Person('person1') var person2 = new Person('person2') person1.obj.foo1()() // 默认绑定 window person1.obj.foo1.call(person2)() // 默认绑定window person1.obj.foo1().call(person2) // 显示绑定person2 person1.obj.foo2()() // 箭头函数绑定 obj person1.obj.foo2.call(person2)() // 箭头函数绑定 person2 person1.obj.foo2().call(person2) // 箭头函数绑定 obj
第八题
// 当函数的参数有默认值时, 会形成一个新的作用域, 这个作用域用于保存参数的值(所以不会修改全局的变量) var x = 0 function foo(x, y = function() { x = 3; console.log(x) }) { console.log(x) // 1 var x = 2 console.log(x) // 2 y() // 3 console.log(x) // 2 } foo(1) console.log(x) // 0
ES5一下就懂了
"use strict"; // 当函数的参数有默认值时, 会形成一个新的作用域, 这个作用域用于保存参数的值(所以不会修改全局的变量) var x = 0; function foo(x) { var y = function () { x = 3; console.log(x); }; return function (x) { console.log(x); // 1 var x = 2; console.log(x); // 2 y(); // 3 console.log(x); // 2 }(x); } foo(1); console.log(x); // 0
"use strict"; // 当函数的参数有默认值时, 会形成一个新的作用域, 这个作用域用于保存参数的值(所以不会修改全局的变量) var x = 0; function foo(x) { var y = function () { x = 3; console.log(x); }; y(); // 3 console.log(x); // 3 return function (x) { console.log(x); // 3 var x = 2; console.log(x); // 2 y(); // 3 console.log(x); // 2 }(x); } foo(1); console.log(x); // 0
第九题 原型链
Function.prototype.a = function () { console.log("我是a"); }; Object.prototype.b = function () { console.log("我是b"); }; function A() {} var c = new A(); A -> Function.prototype -> Object.prototype c -> A.prototype -> Object.prototype A.a(); // 我是a A.b(); // 我是b c.a(); // undefined() c.b(); // 我是b Function.b(); // 我是b Object.a(); // 我是a
第十题
请用你的语言来描述原型链和this指向的相关概念~
原型链:
如果在对象上没有找到需要的属性或者方法引用,引擎就 会继续在 [[Prototype]] 关联的对象上进行查找。同理,如果在后者中也没有找到需要的 引用就会继续查找它的 [[Prototype]],以此类推。这一系列对象的链接被称为“原型链”。
this指向:
分为默认,隐式,显示,new,箭头函数5大绑定。前面4种看函数怎么调用,谁调用,绑定谁。最后一种靠继承包含箭头函数的函数绑定的this。
绑定优先级:new > 显示 > 隐式 > 默认
第十一题
原型链中this的指向问题
function Fn(){ this.name = 'xiaoming' this.age = '12' } function Fn1(){ this.age = 18 } Fn.prototype.getName = function () { console.log(this.name); } Object.prototype.getAge = function (){ console.log(this.age); } let f1 = new Fn() f1.getName() // xiaoming f1.getAge() // 12 let f2 = new Fn1() f2.getAge() // 18