数据类型容易忽略的细节

简介: 数据类型容易忽略的细节

第一题

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
目录
相关文章
|
7月前
|
C#
C#学习相关系列之数据类型类的三大特性(二)
C#学习相关系列之数据类型类的三大特性(二)
|
机器学习/深度学习 设计模式 算法
类型体系与基本数据类型(第三节)
类型体系与基本数据类型(第三节)
54 0
|
7月前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
145 0
|
7月前
|
存储 JavaScript
数据类型容易忽略的细节
数据类型容易忽略的细节
60 0
|
存储 编译器 C#
C# 变量数据类型的使用和案例(基础篇)
C# 变量数据类型的使用和案例(基础篇)
|
存储 机器学习/深度学习 并行计算
类型体系与基本数据类型(第二节)
类型体系与基本数据类型(第二节)
52 0
|
存储 编译器
数据类型的本质分析
数据类型的本质分析
102 0
|
存储 编译器 C语言
C语言数据类型类型及语句(各种详细的细节以及基础+持续更新中
C语言数据类型类型及语句(各种详细的细节以及基础+持续更新中
229 0
C语言数据类型类型及语句(各种详细的细节以及基础+持续更新中
|
存储 编译器 Go
基本数据转换细节讨论 | 学习笔记
简介:快速学习基本数据转换细节讨论
|
算法 安全 JavaScript
用任意类型编写代码——一文带你了解泛型编程
泛型编程中,代码可以被处理成任何类型的对象。泛型编程与非泛型编程的区别是,数据的“类型”(通常标记为 T )没有被明确说明。