-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaScript 中的原型和原型链 #72
Comments
前端面试必备 | 使用原型和构造函数创建对象(原型篇:上)
在这篇文章中,我们将会讨论 JavaScript 中的原型是什么,以及在 JavaScript 中如何实现面向对象编程。 使用构造函数
|
前端面试必备 | 古怪的原型(鸡生蛋还是蛋生鸡)(原型篇:中)
以下四行足以使大多数 JavaScript 开发人员感到困惑: Object instanceof Function
// true
Object instanceof Object
// true
Function instanceof Object
// true
Function instanceof Function
// true JavaScript 中的原型是极其难以理解的概念之一,但是你不能逃避它。不管你怎么忽略,你终究会在开发过程中碰到原型难题。 所以,让我们直面它吧。 从基础开始,JavaScript 中包含以下数据类型:
上面的数据类型中除了对象,其他的都是原始数据类型,他们存储对应类型的数据。 而对象 在 JavaScript 中,可以使用构造函数 ( JavaScript 中的函数是可以 “调用” 的特殊对象。我们使用 在开始了解原型之前,我想澄清一下 JavaScript 中有两个原型:
var obj = {} // 对象字面量
var obj1 = new Object() // 构造函数创建对象 上面两个语句对于创建一个新的对象来讲是一样的,事实上当我们执行上面任何一条语句的时候都发生了很多事情。 当我创建一个新对象的时,创建的是一个空对象。事实上,它并不是空的,因为它是对象构造函数 如果我们查看 obj.__proto__ === Object.prototype
// true 每个函数的 Object.prototype.constructor === Object
//true 在上面的图片中,左边是 如果你仔细看,你会发现
Object.__proto__ === Function.prototype
//true 如果你仔细的看上面的图,你也会发现
Function.prototype === Function.__proto__
// true 文章前面也说过,函数的 Function.prototype.constructor === Function
// true 上面这张图非常有趣!! 我们再来捋一遍, Function.prototype.__proto__ == Object.prototype
// true 所以有了下面这张图: // instanceof 操作符
a instanceof b
现在我们回到文章最开始的四个 Object instanceof Function
Object.__proto__.constructor === Function
Object instanceof Object
Object.__proto__.__proto__.constructor === Object
Function instanceof Function
Function.__proto__.constructor === Function
Function instanceof Object
Function.__proto__.__proto__.constructor === Object 上面的情况太让人纠结了,哈哈!!但是我希望能简单点理解。 这里我有一点没有提出来,那就是 事实上,它其实有一个 Object.prototype.__proto__
// null
Object.create.__proto__ === Function.prototype
// true 你也可以探索其他的构造函数,如 额外的问题: 这里有几个困扰我一段时间的问题:为什么 这里 https://stackoverflow.com/a/32929083/1934798 给出了解答。 另一个问题是:原始数据类型是如何调用对应的方法的,如 我把上面两个问题贴到这里。 第一个: 为什么 在 ES6 中
函数原型对象是为了兼容 ES6 之前的版本的 JS,这也不会让 能作为构造函数的函数必须有一个 下面有一些非构造函数的例子。
typeof Math.pow; // "function
'prototype' in Math.pow; // false
typeof document.createElement('object'); // "function
'prototype' in document.createElement('object'); // false
typeof (x => x * x); // "function
'prototype' in (x => x * x); // false 第二个:如何理解包装对象 在文章的最开始我们列出了 JS 中的数据类型,其中(这里不考虑 我们平常也会看到下面的操作: var str = 'hello'; //string 基本类型
var s2 = str.charAt(0);
alert(s2); // h 上面的 主要是因为:字符串去调方法的时候,基本类型会找到对应的包装对象类型,然后包装对象把所有的属性和方法给了基本类型,然后包装类型消失。 其过程大概是下面这样: var str = 'hello'; //string 基本类型
var s2 = str.charAt(0); //在执行到这一句的时候 后台会自动完成以下动作 :
(
var str = new String('hello'); // 1 找到对应的包装对象类型,然后通过包装对象创建出一个和基本类型值相同的对象
var s2 = str.chaAt(0); // 2 然后这个对象就可以调用包装对象下的方法,并且返回结给s2.
str = null; // 3 之后这个临时创建的对象就被销毁了, str =null;
)
alert(s2);// h
alert(str);// hello 注意这是一瞬间的动作 实际上我们没有改变字符串本身的值。 也就是说,当原始值需要用到包装对象的属性或者方法的时候,会构造一个临时的包装对象出来,使用了之后就销毁了。所以即使给这个原始值赋值,由于赋值之后对象会被销毁,之后从这个原始值上并不能获取到对应的属性。 看下面的面试题:把原始值当做一个对象用的时候,所使用的的方法会对隐式产生的包装对象起作用,但不对原始值起作用。 var str="hello";
str.number = 10; // 包装对象消失
alert(str.number); // undefined 最后往期精彩:
关注公众号可以看更多哦。 感谢阅读,欢迎关注我的公众号 云影 sky,带你解读前端技术,掌握最本质的技能。关注公众号可以拉你进讨论群,有任何问题都会回复。 |
前端面试必备 | 千万不能错过的原型操作方法及其模拟实现(原型篇:下)这篇文章主要讲解原型的查找、变更、判断和删除,附带着对原型的作用方式做一下回顾。
|
JavaScript 中创建对象的那些事儿本文原载自 http://js-professional.lxfriday.xyz/blog/2019/12/31/JavaScript%E4%B8%AD%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B%E5%84%BF,作为学习笔记总结呈现。 创建对象的几种基本方式
关于 工厂模式function createPerson(name, age, job) {
const o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
console.log(this.name);
};
return o;
}
const person1 = createPerson("Nicholas", 29, "Software Engineer");
const person2 = createPerson("Greg", 27, "Doctor"); 每一次调用上面的 缺点:没有解决这个对象是一个什么类型的对象(没有更精确的对象标识,即没有精确的构造函数)。 构造函数模式将工厂改造成构造函数之后,如下 function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
console.log(this.name);
};
}
const person1 = new Person("Nicholas", 29, "Software Engineer");
const person2 = new Person("Greg", 27, "Doctor");
person1.sayName(); // Nicholas
person2.sayName(); // Greg 构造函数和工厂的区别:
使用构造函数创建对象将会有以下几个步骤:
缺点:每次实例化一个新对象,都会在内部创建一个 所以上面的代码经过改造之后,变成下面这样: function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName() {
console.log(this.name);
}
const person1 = new Person("Nicholas", 29, "Software Engineer");
const person2 = new Person("Greg", 27, "Doctor");
person1.sayName(); // Nicholas
person2.sayName(); // Greg 上述的做法虽然解决了重复创建匿名函数的问题,但是又引入了新的问题。 外面的 原型模式函数创建之后都会有一个 使用原型的好处在于它所有的属性和方法会在实例间共享,并且这个共享的属性和方法是直接在原型上设置的。 function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
console.log(this.name);
};
const person1 = new Person();
person1.sayName(); // "Nicholas"
const person2 = new Person();
person2.sayName(); // "Nicholas"
console.log(person1.sayName == person2.sayName); // true 关于原型的工作原理,可以查看下面三篇文章,看完之后相信你对原型的认识比大多数人都要深刻!
理解原型的层级对象中属性的查找机制: 当从对象中访问一个属性的时候,JS 引擎将会按属性名进行查找。JS 引擎会先查找对象自身。如果找到了这个属性,就会停止查找并返回属性对应的值,如果在对象自身没有找到,则会通过原型链到原型对象中继续查找这个属性,如果找到了这个属性,就会停止查找并返回属性对应的值,否则会继续到上层原型链中查找,直到碰到 当一个属性添加到实例中时,这个属性会覆盖原型上的同名属性,这个覆盖指的是查找的时候不会到原型中查找同名属性。即使属性的值被赋值为 可以使用
|
形成文章
ref
看下面的问题
The text was updated successfully, but these errors were encountered: