从零开始学_JavaScript_系列(20)——js系列<7>(函数原型的两种声明方式、函数的作用域)

简介:   (20)函数的原型 ①Object.create(obj) 根据原型obj创建一个对象; 例如: var obj = {    a: 1}var o1 = Object.create(obj);console.log(obj);console.log(o1); 输出为: Object {a: 1} Object {}   ②使用构造函数方法: 使用构造函

 

(20)函数的原型

①Object.create(obj)

根据原型obj创建一个对象;

例如:

var obj = {
    a: 1
}
var o1 = Object.create(obj);
console.log(obj);
console.log(o1);

输出为:

Object {a: 1}

Object {}

 

②使用构造函数方法:

使用构造函数,通过new来创建一个实例(之前有,这里略)

 

①和②之间的区别:

通过②的继承:

var obj = {
    a: 1
}
var o1 = Object.create(obj);
var o2 = Object.create(o1);
o1.b = 5;
o2.c = 2;
console.log(o1.b);
console.log(o2.b);

o1和o2都有属性b,并且值为5;

 

但是,通过继承来的,则不一样。

var obj = function () {
    a: 1
}
var o1 = function(){}
o1.prototype = new obj();
var o2 = function(){}
o2.prototype = new o1();
o1.b = 5;
o2.c = 2;
console.log(o1.b);
console.log(o2.b);

输出是5和undefined

 

通过查看console属性可以发现,Ojbect.create,其原型链是直接链接到创建时的原型对象的。

例如假设o2没有属性b,那么其值则为o1的属性b的值,假如o1.b的值被更改,那么o2.b的值也会被更改。

如代码:

var obj = {
    a: 1
}
var o1 = Object.create(obj);
var o2 = Object.create(o1);
o1.b = 3;
console.log(o2.b);
o1.b = 5;
console.log(o2.b);

其输出的值分别是3和5

 

 

④hasOwnProperty()

通过Object.create()方法声明的变量,其原型的属性,在自身调用 hasOwnProperty()会提示false

var obj = {
    a: 1
}
var o1 = Object.create(obj);
var o2 = Object.create(o1);
o1.b = 5;
console.log(o2.hasOwnProperty("b"));
o2.b = 2;
console.log(o2.hasOwnProperty("b"));

例如,第一个是true,第二个是false

但需要注意,这种方法无法通过

o2.prototype.b = 5;

来为之设置属性

 

而另一种方法和其的区别在于,可以通过o2.prototype.b = 5;来设置属性,以及继承。

 

 

 

(21)函数的作用域

①静态作用域:(JS使用的是这种)

var x = 1;
function a() {
    console.log(x);
}
function b() {
    var x = 2;
    a();
}
b();

输出结果是1,而不是2。

因为a()定义在window里,而不是在b()里,所以使用的是window中的x,而不是b中的x,如以下代码输出结果便为2:

var x = 1;
function b() {
    var x = 2;
    function a() {
        console.log(x);
    }
    a();
}
b();

 

 

②JS变量的作用域:全局作用域、函数作用域。没有块级作用域(即{}之间声明的变量的作用域);

 

③with方法的临时作用域:

var x = 1;
with ({x: 2}) {
    function a() {
        console.log(x);
    }
    (function () {
        console.log(" " + x);   //输出2
        a() //输出1
    })();
}
console.log(x); //输出1

 

之所以,是因为匿名函数可以理解为在函数内部创建并执行的(类似一个表达式),因此其内部变量的作用域是在with环境创建的临时作用域。(这个作用域,是x=2的作用域)

 

而a函数是声明的,因此其作用域是全局的(因为没有块级作用域,只有全局和函数内部的)。(函数被预解析时,知道其作用域是全局的)

 

由于with环境作用域是临时的,并且声明的是一个对象,因此不会对全局变量x进行修改。

 

 

 

目录
相关文章
|
3天前
|
JavaScript 前端开发 Java
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
本文介绍了JavaScript中常用的函数和方法,包括通用函数、Global对象函数以及数组相关函数。详细列出了每个函数的参数、返回值及使用说明,并提供了示例代码。文章强调了函数的学习应结合源码和实践,适合JavaScript初学者和进阶开发者参考。
13 2
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
|
2天前
|
前端开发 JavaScript 开发者
除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
|
16天前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。
|
18天前
|
存储 JavaScript 前端开发
JS函数提升 变量提升
【10月更文挑战第6天】函数提升和变量提升是 JavaScript 语言的重要特性,但它们也可能带来一些困惑和潜在的问题。通过深入理解和掌握它们的原理和表现,开发者可以更好地编写和维护 JavaScript 代码,避免因不了解这些机制而导致的错误和不一致。同时,不断提高对执行上下文等相关概念的认识,将有助于提升对 JavaScript 语言的整体理解和运用能力。
|
21天前
|
存储 JavaScript 前端开发
JavaScript数据类型全解:编写通用函数,精准判断各种数据类型
JavaScript数据类型全解:编写通用函数,精准判断各种数据类型
15 0
|
6月前
|
前端开发 JavaScript
JavaScript中的原型和原型链
JavaScript中的原型和原型链
|
6月前
|
JavaScript 前端开发
【面试题】最详尽的 JS 原型与原型链终极详解(一)
【面试题】最详尽的 JS 原型与原型链终极详解(一)
135 0
|
6月前
|
JavaScript 前端开发
手把手教你学会js的原型与原型链,猴子都能看懂的教程
手把手教你学会js的原型与原型链,猴子都能看懂的教程
|
6月前
|
JavaScript 前端开发
JavaScript原型,原型链
JavaScript原型,原型链
|
5月前
|
设计模式 JavaScript 前端开发
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
JavaScript的继承机制基于原型链,它定义了对象属性和方法的查找规则。每个对象都有一个原型,通过原型链,对象能访问到构造函数原型上的方法。例如`Animal.prototype`上的`speak`方法可被`Animal`实例访问。原型链的尽头是`Object.prototype`,其`[[Prototype]]`为`null`。继承方式包括原型链继承(通过`Object.create`)、构造函数继承(使用`call`或`apply`)和组合继承(结合两者)。ES6的`class`语法是语法糖,但底层仍基于原型。继承选择应根据需求,理解原型链原理对JavaScript面向对象编程至关重要
121 7
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略